How does a composer handle multiple versions of the same package?

It may (should) ask somewhere, but I cannot find the answer. If someone provides a link, I can delete this post !:

Just trying to plunge into some composer (perhaps applies to other package managers).

Basically, I just want to know what the composer does in the following scenarios:

one.

My main project has a dependency:

"guzzlehttp/guzzle": "5.0.*", 

My external package has a dependency on

 "guzzlehttp/guzzle": "5.0.*", 

Does composer create guzzlehttp / guzzle once because he knows that he needs it only once?

2. The same scenario, but in the future, if someone updates the main project:

 "guzzlehttp/guzzle": "6.0.*", 

Now the composer will install 2 versions of guzzle (5 and 6) (I suppose this is what it should do), or will it accept the highest version (i.e. 6)? Also, if there are 2 versions, will this cause conflicts because the namespaces can be the same?

thanks

+14
symfony composer-php
source share
2 answers

To Question 1

Yes Composer can only install one version of each extension / package.

To Question 2

Due to answer 1: The composer will consider your main project and external package as incompatible.

In this case, you could

  • Stay with version 5 in your main project.
  • ask the owner of the external package to upgrade to version 6 if it is compatible with.
  • open the external package and make it compatible with version 6.
+19
source share

Today we had a situation where we used several libraries, one of which used Guzzle v5, and the other - Guzzle v6. Upgrading (or downgrading) was not an acceptable option, as it was third-party code, so we should be able to install both versions of Guzzle.

Here is what we did. This is a complete hack , and I would advise you to do this only as a last resort. This works, but updating your calling code to use only one version is a much better option.

The trick is that you need to rename the space of one of the two versions. In our case, we decided to change v6 to GuzzleHttp6. Here's how to do it:

  1. Make sure your composer.json v6 is enabled:

 "require": { "guzzlehttp/guzzle": "^6.2" // possible other stuff }, 
  1. composer install to get Guzzle v6 all its dependencies are installed.
  2. Move the /vendor/guzzlehttp to the new /vendor-static/guzzlehttp .
  3. Search and replace case sensitive in the /vendor-static directory to replace GuzzleHttp with GuzzleHttp6 . This effectively migrates Guzzle 6 code to the new namespace.
  4. Now update your composer.json so that it includes Guzzle's own dependencies manually, and then automatically upload the code to the /vendor-static folder. Note that you will want to REMOVE the operator main eats requirements (or change it, including sting 5);

 "require": { "guzzlehttp/guzzle": "~5", "psr/http-message": "~1.0", "ralouphie/getallheaders": "^2.0.5" }, "autoload": { "files": ["vendor-static/guzzlehttp/guzzle/src/functions_include.php", "vendor-static/guzzlehttp/psr7/src/functions_include.php", "vendor-static/guzzlehttp/promises/src/functions_include.php"], "psr-4": { "GuzzleHttp6\\": "vendor-static/guzzlehttp/guzzle/src/", "GuzzleHttp6\\Psr7\\": "vendor-static/guzzlehttp/psr7/src/", "GuzzleHttp6\\Promise\\": "vendor-static/guzzlehttp/promises/src/" } }, 
  1. composer update to remove the old Guzzle v6 and install Guzzle v5. This will also install the dependencies psr/http-message and ralouphie/getallheaders .

  2. You may need to run composer dump-autoload to force the autoloader to add new include paths. Theoretically, this should happen with composer update but I had to force it.

  3. Now update your calling code; instead of calling \ GuzzleHttp , you will call \ GuzzleHttp6 .

And that is it. You should be able to run both at the same time. Please note that no matter what version of Guzzle v6 you have in the /vendor-static directory, it will exist forever, so you can update it from time to time.

0
source share

All Articles