我有一个包含多个模块的项目。每个模块本身都使用Composer,并且大部分独立于其他模块。
但是,某些模块共享具有不同版本的依赖项。这些依赖项在大多数情况下是向后兼容的,并使用语义版本控制。
我想确保具有最高语义版本的依赖关系优先。这将允许所有模块共享相同的依赖关系,并且这些依赖关系的向后兼容性将确保没有任何中断。
我的计划是通过控制我在各个自动加载器上调用require_once
的顺序来实现此目的。下面的代码是一个例子,实际上是生成的。
require_once(__DIR__ . '/moduleA/vendor/autoload.php');
require_once(__DIR__ . '/moduleB/vendor/autoload.php');
require_once(__DIR__ . '/moduleC/vendor/autoload.php');
我所做的主要假设是,如果在另一个之前需要自动加载器,它将优先于后者。
我发现的是相反是真的。 最后的自动加载器似乎优先于其他自动加载器。
考虑类Foo\MyClass
是这些模块之间共享的依赖项。我期待上述加载顺序,Foo\MyClass
将从moduleA/vendor/...
中获取。
相反,它来自moduleC/vendor/...
。
我可以翻转生成的订单以解决此问题,但我想验证PHP自动加载器是否存在可预测的顺序。
是否有PHP执行自动加载器的顺序?多个Composer自动加载器会以任何方式影响这个吗?
感谢。
答案 0 :(得分:8)
实际上,你已经陷入了混乱,但是你已经离开这个烂摊子的一半了。
您的情况有什么不好之处在于您的模块可能依赖于不兼容的第三方库。你提到它们使用语义版本控制,但这只包括向上兼容性,例如"如果以与旧版本兼容的方式添加新功能,则会增加次要版本"。这意味着这个新版本不向后兼容!
假设模块A使用的是版本1.0.7,而模块B使用的是版本1.2.5。该库在1.2版本中添加了一个新方法,模块B正在使用该方法。模块B可以运行模块A的类版本1.0.7吗?当然不是。您希望两个模块都以两个模块的最高兼容版本运行,1.2.5。
如何获得这个?仅使用一个Composer自动加载器,只使用一个中央依赖关系定义。
如果你可以创建一个包含所有模块A,B和C的依赖关系的composer.json
文件,并且每个模块都声明它对其他库的依赖关系,那么Composer会收集所有这些库,计算最好的"可用的版本,并创建一个自动加载器,只能明确加载这些库。
增加的好处:每个库只有一个版本,没有重复项。只有一个自动加载器对象具有关于所有可用类的全局知识(可以优化自动加载一点)。
你在那里一半。您的每个模块必须已有一个本地composer.json
,其中说明了版本要求。添加自动加载该模块本身的定义,并为其命名。然后,您可以在中心composer.json
中引用该名称(如果它们是私有的,您可能需要添加存储库),并且您差不多完成了。如果您确实需要在定义的路径中使用这些模块,可能会有一些摆弄路径。
但那是关于它的。
然后你解决另一件事:如果模块A需要模块B的一小部分怎么办?使用Composer,您可以将所有依赖项与所有库一起声明,即使您忘记安装模块B,Composer也会为您完成,或者提醒您。