作曲家如何处理同一个包的多个版本?

tim*_*c22 20 symfony composer-php

这可能(应该)在某个地方被问过,但我似乎无法找到答案.如果有人提供链接,我可以删除这篇文章!:

只是试图让我的头脑周围的一些作曲家(可能也适用于其他包经理)的功能.

基本上我只是想知道作曲家在以下场景中做了什么:

1.

我的主项目有一个依赖:

"guzzlehttp/guzzle": "5.0.*",
Run Code Online (Sandbox Code Playgroud)

我的外部包依赖于

"guzzlehttp/guzzle": "5.0.*",
Run Code Online (Sandbox Code Playgroud)

作曲家一次安装guzzlehttp/guzzle,因为它知道它只需要一次吗?

2.相同的情况,但将来如果有人更新要使用的主项目:

"guzzlehttp/guzzle": "6.0.*",
Run Code Online (Sandbox Code Playgroud)

作曲家现在会安装两个版本的guzzle(5和6)(我认为这是应该做的),还是会采用最高版本(即6)?此外,如果有2个版本会导致任何冲突,因为名称空间可能是相同的?

谢谢

Pᴇʜ*_*Pᴇʜ 23

问题1

是Composer只能安装每个扩展/包的一个版本.

问题2

由于答案1:Composer会认为您的主项目和外部包不兼容.

在这种情况下你可以

  • 在主项目中继续使用第5版.
  • 如果兼容,请要求外部包所有者升级到版本6.
  • fork外部包并使其与版本6兼容

  • 我想这不会起作用,因为不同版本中的相同扩展/包具有相同的命名空间和几乎相同的功能,这使得它们不兼容.这不是一个功能,也不是一个bug.你不能在同一个命名空间中拥有2倍相同的功能. (5认同)
  • 有没有人找到任何解决方法?还是作曲家团队认为这是一个功能而不是一个错误? (3认同)

dor*_*dal 14

我们今天遇到了一种情况,我们使用了多个库,一个使用 Guzzle v5,另一个使用 Guzzle v6。升级(或降级)不是一个可行的选择,因为它是第三方代码,所以我们必须能够安装 Guzzle 的两个版本。

这就是我们所做的。这是一个完全的 FRACKING HACK,我建议这样做只是作为绝对的最后手段。它有效,但更新您的调用代码以仅使用一个版本是一个更好的选择。

诀窍是您需要重新命名两个版本之一。在我们的例子中,我们决定将 v6 更改为 GuzzleHttp6。以下是如何做到这一点:

  1. 确保您composer.json已启用 v6:

"require": {
        "guzzlehttp/guzzle": "^6.2"
        // possible other stuff
    },
Run Code Online (Sandbox Code Playgroud)

  1. composer install 安装 Guzzle v6 的所有依赖项。
  2. /vendor/guzzlehttp目录移动到新/vendor-static/guzzlehttp目录。
  3. /vendor-static目录进行区分大小写的查找和替换,以将GuzzleHttp替换为GuzzleHttp6。这有效地将 Guzzle 6 代码带入了一个新的命名空间。
  4. 现在更新您composer.json以手动包含 Guzzle 自己的依赖项,然后自动加载/vendor-static文件夹中的代码。请注意,您需要删除主要的 guzzle require 语句(或将其更改为包含 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/"
            }
        },
Run Code Online (Sandbox Code Playgroud)

  1. composer update删除旧的 Guzzle v6,并安装 Guzzle v5。这也将安装psr/http-messageralouphie/getallheaders依赖项。

  2. 您可能需要执行 acomposer dump-autoload来强制自动加载器添加新的包含路径。理论上这应该发生,composer update但我不得不强迫它。

  3. 现在更新您的调用代码;而不是调用\GuzzleHttp,您将调用\GuzzleHttp6

就是这样。您应该能够同时运行两者。请注意,您在/vendor-static目录中获得的任何 Guzzle v6 版本都将永远存在,因此您可能需要不时更新它。

  • 在我们的例子中,否——使用 Guzzle5 的父库是专有的第三方代码,已使用 Ioncube 加载程序加密,并且不可更改。我们必须有一个解决方案来支持 Guzzle5 和 Guzzle6。 (2认同)