Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent PHP namespace conflicts (pre-bundled packages)

Let's assume we have a PHP project with dependencies A and B each depending on PHP library X, but in a different version.

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.

Now, many PHP applications allow their users to install plugins simply by uploading pre-bundled packages and extracting them to a specific plugin directory.

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.

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...).

My question is:

  • How would you solve this problem? Can you recommend this approach or is there a better solution?
like image 352
le_m Avatar asked May 21 '16 03:05

le_m


1 Answers

There is no solution without changing the code. If two versions of ´\Vendor\AnyClass´ 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.

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.

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.

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.

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.

like image 65
Sven Avatar answered Oct 21 '22 05:10

Sven