当软链碰到composer并在autoload中使用files


背景

这个sdk是一个历史项目了,后边做了composer化,拆分成了一个worker和一个composer包。再由worker引入composer包的形式继续使用。

很多个项目均引入了此sdk。

细节

目录结构

├─other_project
│   main.php
│
└─sdks
 │  sdk_link.php
 │
 └─client
     sdk.php

使用方式

两个目录,other_project表示一个项目,此项目会引入sdk_link.php。而sdk_link.php实际上是软连接,连接的是sdks/client/sdk.php。

sdks是所有sdk的目录,一般的习惯都是把实际的sdk文件链接到根目录(项目组历史遗留陋习)。

问题

在sdk升级到composer的时候,由于要兼容历史使用方式(不带命名空间的类)。所以,在autoload中用files指定引入sdk.php文件(重点)。

"autoload":{
    "psr-4": {
      "xx\\client\\": "client"
    },
    "files": ["client/sdk.php"]
  }

 

在使用此sdk的项目中使用

require_once "sdks/sdk_link.php";

引入sdk进行使用。

此时报错:sdk.php文件中定义的类不能重复定义。

原因

虽说使用了require_once,但是composer生成的autoload用的是require(重点),导致重复加载了。

 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
    require $file;

    $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
}

总结

使用require(require_once)引入composer化的项目中的文件时,一定要确保此文件没有在composer.json中通过files定义自动加载。

Ps:在无命名空间的项目中直接require composer项目一定要非常小心。。。

Ps:赶紧把项目升级到composer吧。。。。。。


发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注