How does composer handle multiple versions of the same package?

前端 未结 2 1449
鱼传尺愫
鱼传尺愫 2020-12-08 20:33

This may (should) have been asked before somewhere but I can\'t seem to find an answer. If someone provides a link I can delete this post!:

Just trying to get my hea

相关标签:
2条回答
  • 2020-12-08 20:59

    We had a situation today where we were using multiple libraries, and one used Guzzle v5 and the other Guzzle v6. Upgrading (or downgrading) was not a viable option, as it was third party code, so we had to be able to install both versions of Guzzle.

    Here's what we did. This is a TOTAL FRACKING HACK, and I'd advise doing this only as an absolute last resort. It works, but updating your calling code to use just one version is a much better option.

    The trick is that you need to re-namespace one of the two versions. In our case we decided to change v6 to GuzzleHttp6. Here's how to do that:

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

    "require": {
            "guzzlehttp/guzzle": "^6.2"
            // possible other stuff
        },

    1. composer install to get Guzzle v6 all its dependencies installed.
    2. Move the /vendor/guzzlehttp directory over to a new /vendor-static/guzzlehttp directory.
    3. Do a case-sensitive find & replace on the /vendor-static directory to replace GuzzleHttp with GuzzleHttp6. This effectively brings the Guzzle 6 code into a new namespace.
    4. Now update your composer.json to include Guzzle's own dependencies manually, and then autoload the code in the /vendor-static folder. Note you'll want to REMOVE the main guzzle require statement (or change it include guzzle 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 psr/http-message and ralouphie/getallheaders dependencies.

    2. You may need to do a composer dump-autoload to force the autoloader to add the new include paths. In theory this should happen on composer update but I had to force it.

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

    And that's it. You should be able to run both concurrently. Note that whatever version of Guzzle v6 you've got in the /vendor-static directory will be there forever-more, so you may want to update that from time-to-time.

    0 讨论(0)
  • 2020-12-08 21:05

    To question 1

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

    To question 2

    Because of answer 1: Composer would consider your main project and the external package as incompatible.

    In this case you could

    • stay with version 5 at your main project too.
    • ask the external package owner to upgrade to version 6 too if it's compatible to.
    • fork the external package and make it compatible to version 6 yourself
    0 讨论(0)
提交回复
热议问题