Prestashop Guzzle 冲突

Posted

技术标签:

【中文标题】Prestashop Guzzle 冲突【英文标题】:Prestashop Guzzle Conflict 【发布时间】:2019-05-18 18:44:38 【问题描述】:

我正在通过包含一个使用guzzle6.0 的包来更新prestashop 模块。

Prestashop 1.7 使用旧版本的 Guzzle 5。

当我在 Prestashop 上安装插件时,包含的 Guzzle 软件包版本与 Prestashop 版本冲突,导致以下 php 错误。

未捕获的 PHP 异常 InvalidArgumentException:“魔术请求方法需要 URI 和可选选项数组”,位于 /var/www/html/modules/package/vendorpackage/guzzlehttp/guzzle/src/Client.php 第 81 行 “异常”: "[object] (InvalidArgumentException(code: 0):Magic request 方法需要一个 URI 和可选的选项数组,位于 /var/www/html/modules/package/vendorpackage/guzzlehttp/guzzle/src/Client.php:81)" []

我发现了一些其他类似问题的例子:

PrestaShop module classes not found (namespaces) http://forge.prestashop.com/browse/BOOM-2427 Prestashop 1.6, conflict: 2 different modules requiring same class, different versions https://github.com/Nexmo/nexmo-php/issues/77

基于这些,我对如何解决这个问题有一些想法。这些都不是正确的方法。使用composer 肯定有更简洁的方法来处理此类问题吗?

从包含的包中删除 Guzzle - 这是最简单的一个,我的问题是,如果我删除此依赖项,它会在哪里停止,怎么说任何其他依赖项都不会冲突以后不能删除的那一行?

可以检查包中 Guzzle 的版本并根据加载的调用交换调用 - 与上面的问题类似,我可以修复以确定我应该使用哪种类型的调用对于这个错误,但我不知道这可能会引发什么其他问题,并且我的代码最终可能会出现每个版本的语句。

在插件中手动更改 guzzle 的命名空间。所以我可以进入我的包的供应商文件夹并为包强制指定一个特定的命名空间,我猜这将解决我的问题,但我失去了安装可重用包的意义。

Fork Guzzle 并参考该版本。我可以分叉 guzzle 并将其作为 VCS 包包含在插件中。这里的问题是我必须保持这种状态向前发展。

【问题讨论】:

相当老套,但如果你真的想走这条路,你可以注册一个自定义自动加载器,它会将你的 Guzzle 包文件版本复制到临时文件中,并将文件中的命名空间替换为你想要的任何内容然后包含临时文件。 我认为这里没有什么好方法——主要问题应该是为什么有人为 Prestashop 发布了一个明显与 PS 不兼容的模块。是否可以请求该依赖模块的旧版本? 【参考方案1】:

你有两个解决方案:

查找使用 GuzzleHttp 5(如果可用)的软件包版本。 寻找替代方案。

不推荐的解决方案:

更改包中 Guzzle 的命名空间并安装 guzzle 6。 (例如:use GuzzleHttp\ => 'use GuzzleHttpSix\'

发生这种情况是因为使用的命名空间存在冲突(witch 与 guzzle 5 和 6 相同)。 Prestashop 优先考虑它的包。

【讨论】:

【参考方案2】:

这个问题没有说明主要目标是什么。如果您的主要目标是更新 Prestashop(而不是解决特定错误),那么我建议您创建 Prestashop 环境的本地安装 - 并使用它来手动更新您的生产环境,逐个文件。我可以通过以下方式完成:

    在本地计算机上以预期版本(1.7.5?)创建全新的 Prestashop 安装(使用新数据库)。 Composer 将确保两个安装使用相同的依赖项。

    备份您的生产数据库,并在本地数据库服务器上恢复它。

    重新配置本地 Prestashop 以与本地数据库通信。

    升级本地 Prestashop。检查此更新的安装是否有效。

    使用差异工具(例如,Beyond Compare)比较本地安装和远程安装。两种安装之间的任何差异都需要逐个处理:

    将新的/更新的代码从本地安装复制到远程安装。 从远程安装中删除所有过时的文件。

    更新生产数据库。

记得在开始之前备份软件和数据库。

【讨论】:

主要目标是能够在贡献的插件中包含一个 guzzle 版本,而不会与 Prestashop 自己的版本发生冲突。虽然这是如何修复单个 Prestashop 网站的绝佳示例,但它并不能解决我正在寻找的问题。【参考方案3】:

您可以在您的模块composer.json 文件中使用"guzzlehttp/guzzle": "~5.0",,而您使用的版本与使用prestashop 的版本相同。

【讨论】:

否:如果 OP 使用另一个依赖于 Guzzle v6 的模块,则无法在自己的模块中要求另一个版本【参考方案4】:

简短的回答:你无能为力。

长答案:鉴于我处于同样的情况,我找到了解决您问题的方法。

如果你的模块依赖于一个依赖于 Guzzle 的包,并且如果该包在你的控制之下,你可以让你的包使用HTTPlug。它是一种抽象,它依赖于其他人,包括一个实际的 HTTP 客户端库。那个人也可能是你,包括 php-http/client-implementation 的不同实现。

随着时间的推移,由于 Prestashop 也可能使用这种方法(以及其他平台),它们最终可能都依赖于 PSR-7 abstractions of HTTP messages。

这并不是您当前问题的真正解决方案,而是一种长期战略,它也可以帮助您解决当前的问题。

【讨论】:

如果另一个模块需要 Guzzle v6,你能解释一下这应该如何工作吗? 我看不出另一个模块不会出现与您自己的模块相同的问题。因此,我对此的看法是包含 PSR7 抽象,并让 Prestashop 在其核心中包含实际客户端(Guzzle)。 嗯,问题一直存在:PS 附带 Guzzle v5 的要求,要安装的模块要求 v6。自 2018 年 10 月起,将 Guzzle 升级到更新版本的 PS 本身已在工单中注明,但没有明显进展 - 所以我认为使用 PSR7 的任何想法都不适用于此处 您问如果另一个模块(不是您正在开发的模块)需要 Guzzle v6 会发生什么。我说不能。我还说过,PSR-7 抽象不是当前问题的解决方案,而是所有模块开发人员的长期解决方案。我们在讨论什么? 我们应该讨论如何帮助 OP 解决他的问题。说明他使用的软件 (Prestashop) 需要返工不是 OP 的责任 - 但正如您所说找到了解决方法,您可能应该进一步解释【参考方案5】:

最简单的方法是为 guzzle 选择一个替代包,但这可能不是最适合你的。

优点

你节省了很多时间

缺点

你使用不同的包来做同样的事情。

中度的方式是 fork guzzle,然后手动更改命名空间。

优点

您不会更改 Prestashop 中的任何内容。

如果 Prestashop 升级到 guzzle 6.0,您可以轻松切换到它。

缺点

你必须保持你自己的定制guzzle。

最困难的方法是自己修补 Prestashop

优点

你得到你想要的一切。

发送拉取请求,您可能会帮助很多其他人。

缺点

如果 Prestashop 继续使用 guzzlehttp 5.0,你最终会陷入打补丁的噩梦。

结论

如果我必须使用 guzzle,我会选择温和的方式。如果我只是想用几行代码做一些特别的事情,我会使用一个替代包。 并且你不能通过 composer 安装同一个包的不同版本。

【讨论】:

以上是关于Prestashop Guzzle 冲突的主要内容,如果未能解决你的问题,请参考以下文章

php [guzzle php] guzzle php #php

guzzlehttp/guzzle

Laravel 5.6模拟Guzzle响应

Guzzle:使用 Guzzle 的 Pool:batch() 和 `sink` 选项进行并行文件下载

prestashop 1.7 新模块

PrestaShop 1.7 如何启用 debug 模式