如何防止 PHP 命名空间冲突(预捆绑包)
假设我们有一个 PHP 项目,其依赖项 A 和 B 分别依赖于 PHP 库 X,但版本不同.
Let's assume we have a PHP project with dependencies A and B each depending on PHP library X, but in a different version.
通常,人们会使用 PHP 依赖管理器,例如 composer,它可以通过在兼容 A 和 B 的版本中包含 X 来解决此冲突 或在无法解决冲突时显示错误.
Usually, one would use a PHP dependency manager such as composer which would either resolve this conflict by including X in a version compatible to both A and B or display an error if the conflict cannot be resolved.
现在,许多 PHP 应用程序允许其用户安装插件,只需上传预先捆绑的包并将它们解压缩到特定的插件目录即可.
Now, many PHP applications allow their users to install plugins simply by uploading pre-bundled packages and extracting them to a specific plugin directory.
如果 A 和 B 是这样的预捆绑插件,并且两者都带有自己的库版本 X,我们可能会遇到问题因为没有依赖管理器可以为我们选择兼容的 X 或在没有时显示错误.
If A and B were such pre-bundled plugins and both would bring their own version of library X, we might run into problems since no dependency manager is available to select a compatible X for us or display an error in case there is none.
为了防止由于 PHP 无法将不同版本的库 X 两次加载到同一个命名空间中而导致的任何此类冲突,我们可以将 A 的 X 和 B 的 X 进入不同的命名空间(这可能很难自动完成,因为我们需要一个 PHP 解析器...).
To prevent any such conflicts caused by the inability of PHP to have library X being loaded twice with different version into the same namespace, we could put A's X and B's X into different namespaces (which might be hard to do automatically as we would need a PHP parser for that...).
我的问题是:
- 您将如何解决这个问题?您能推荐这种方法还是有更好的解决方案?
推荐答案
不改代码就没有解决方案.如果文件系统中确实存在VendorAnyClass"的两个版本,并且执行代码以同时使用它们,则会出现错误,因为不允许重新声明该类,或者因为预期的类不兼容.它只有在类的接口实现相同的情况下才有效,即两个代码兼容.如果不只是一个类,而是一整棵对象树,即使它们提供了兼容的接口,也可能对混合来自不同版本的类做出不良反应,那么兼容性问题就会变得复杂.
There is no solution without changing the code. If two versions of ´VendorAnyClass´ do exist in the filesystem, and code is executed to use them both, either an error appears because redeclaring that class is not allowed, or because the expected class is incompatible. It will only work if the interface of the class is implemented the same, i.e. the two codes are compatible. The problem of compatibility is complicated if it isn't only that one class, but an entire tree of objects that may react badly to mixing classes from different versions, even though they offer a compatible interface.
改变命名空间就是改变代码.谁对此负责?我可以想到一些自动代码解析器,它能够为每个插件添加一个特定的命名空间前缀,但据我所知,该任务还没有在 PHP 中完成.我公司的 Java 人说,那里已经解决了这样的问题,但我没有详细信息.
Changing the namespace is changing the code. Who's responsible for that? I can think of some automatic code parser that would be able to add a specific namespace prefix for each plugin, but that task hasn't been done to my knowledge in PHP. The Java guys in my company made some remarks that such a problem has been solved there, but I have no details.
此外,它会使您的代码库翻倍,并且重复的代码必须只共享您拥有的一个操作码缓存.
Also, it doubles your code base, and the duplicated code has to share only the one opcode cache you have.
我知道 Wordpress 的核心开发人员仍在努力解决这个问题.有一些关于如何使用 Composer 进行依赖管理的编码建议(即插件及其依赖项),但我认为他们目前还没有取得足够的进展.
I know that the core developers of Wordpress are still struggling with this problem. There are some coded suggestions of how to use Composer for dependency management (i.e. plugins and their dependencies), but I don't think they made enough progress for now.
基本上你有两个选择: 1. 创建一个代码命名空间前缀,解析属于插件的所有文件(因此插件作者必须以某种方式包含他的依赖项),更改代码,忍受代码重复,然后查看在调试方面等待您的是什么.缺点是该插件之外的任何代码都不能轻松地直接使用插件代码,因为这意味着知道创建的前缀.2. 实现某种形式的依赖管理,最好使用 Composer,并且不要更改命名空间.
Essentially you have two choices: 1. Create a code namespace prefixer, parse all the files belonging to a plugin (so the plugin author has to include his dependencies somehow), change the code, live with the code duplication, and see what awaits you when it comes to debugging. The downside is that no code outside of that plugin will be easily able to use the plugin code directly because that would mean to know the created prefix. 2. Implement some form of dependency management, preferably using Composer, and don't change the namespaces.
更新:我再次咨询了我的 Java 同事,他们对 Java 的声明基本上与我对 PHP 的声明相同:同一个类名下不能有两个不同版本的类, 甚至对于 Java 也没有魔法",只是将类重命名为不同的命名空间.
Update: I consulted my Java co-workers again, and they basically made the same statement about Java that I made about PHP: You cannot have two different versions of a class under the same class name, and there is no "magic" even for Java but renaming the class to a different namespace.
相关文章