13

I am updating a module by including a package that uses 6.0.

Prestashop 1.7 uses an older version of Guzzle 5.

When I install the plugin on Prestashop the included package's version of Guzzle conflicts with the Prestashop one resulting in the following error.

Uncaught PHP Exception InvalidArgumentException: "Magic request methods require a URI and optional options array" at /var/www/html/modules/package/vendorpackage/guzzlehttp/guzzle/src/Client.php line 81 {"exception":"[object] (InvalidArgumentException(code: 0):Magic request methods require a URI and optional options array at /var/www/html/modules/package/vendorpackage/guzzlehttp/guzzle/src/Client.php:81)"} []

I have found a few other examples of similar issues:

Based on these I have a few ideas for how to get around the issue. None of these feel like the right way to do it. Surely there is a cleaner way to handle issues like this with ?

  • Remove Guzzle from the included package - this is the simplest one, my problem with this is that if I remove this dependency where does it stop, whats to say any other dependencies wont clash later down the line that cant be removed?

  • Can check version of Guzzle in package and swap calls dependent on which one loads - similarly to the issue above I can hack a fix in to determine which type of call I should be using for this bug, but I cant tell what other issues this may raise and my code may end up littered with statements for each version.

  • Manually Change the namespaces of guzzle in the plugin. So I can go into the vendor folder of my package and force a specific namespace for the package, I am guessing this will solve my issue, but I am losing the point of installing a re-usable package.

  • Fork Guzzle and refer to that version. I could fork guzzle and include it as a VCS package in the plugin. Issue here being that I then have to keep that maintained moving forward.

CharliePrynn
  • 3,034
  • 5
  • 40
  • 68
Jonny C
  • 1,943
  • 3
  • 20
  • 36
  • Quite hacky, but if you really want to go this path you could register a custom autoloader, that will copy your version of Guzzle package files into temporary files with the namespace in the file replaced to whatever you want and then include the temporary files instead. – blubear Jan 10 '19 at 05:03
  • I don't think there is a good way to go here - the main question should be why someone released a module for Prestashop that is obviously incompatible with PS. Is it possible to request an older version of that dependent module? – Nico Haase Mar 08 '19 at 13:24

4 Answers4

1

The easiest way is to choose an alternative package for guzzle, but this might not be best for you.

  • Pros

You save a lot of time

  • Cons

You use different package to do the same thing.

The moderate way is to fork guzzle, and then you manually change the namespaces.

  • Pros

You don't change anything in Prestashop.

If Prestashop upgraded to guzzle 6.0, you could easily switch to it.

  • Cons

You have to maintain your own customized guzzle.

The hardest way is to patch Prestashop yourself

  • Pros

You get everything you want.

Send a pull request, you might help a lot of others.

  • Cons

If Prestashop kept using guzzlehttp 5.0, you end up in a patching nightmare.

Conclusions

I would choose the moderate way if I must use guzzle. If I just wanted to do something special in a few lines of code, I would just use an alternative package. And NO you cannot install different versions of the same package by composer.

cwhsu
  • 1,493
  • 24
  • 31
0

Short answer: there's nothing you can do.

Long answer: I sort of found a workaround to your issue, given that I am in the same situation.

If your module depends on a package that depends on Guzzle, and if that package is under your control, you could make your package use HTTPlug. It is an abstraction and it relies on someone else include an actual HTTP client library. That someone could also be you, including a different implementation of php-http/client-implementation.

Over time, as Prestashop might also use this approach (along with other platforms), all of them might end up relying on PSR-7 abstractions of HTTP messages.

It's not really a solution to your current issue, but rather a strategy for the long run, which can also help with where you are right now.

tetele
  • 146
  • 9
  • Can you explain how this should work if another module requires Guzzle v6? – Nico Haase Mar 08 '19 at 13:21
  • I don't see how another module wouldn't have the same problem as your own module. Therefore, my take on this is to include PSR7 abstrations and let Prestashop include the actual client (Guzzle) in its core. – tetele Mar 11 '19 at 12:35
  • Well, the problem is and stays: PS ships with the requirement of Guzzle v5, the module to be installed with the requirement of v6. Upgrading Guzzle to a more recent version PS itself is noted in a ticket since Oct 2018, but there is no obvious progress - so I don't think that any of the ideas of using PSR7 are applicable here – Nico Haase Mar 11 '19 at 13:15
  • You asked what would happen whether another module (not the one you're developing) requires Guzzle v6. I said it can't. I also said that PSR-7 abstractions are *not* a solution to the current issue, but rather a way to go for the long run, for all module developers. What are we discussing? – tetele Mar 12 '19 at 08:39
  • We should be discussing how to help the OP with his problem. Stating that the software he uses (Prestashop) needs to be reworked is not in the responsibility of the OP - but as you said to have found a workaround, you should probably go further in explaining that – Nico Haase Mar 12 '19 at 08:47
0

You got two solutions:

  • Find a version of your package that uses GuzzleHttp 5 (if available).
  • Find an alternative of your package.

And NOT RECOMMENDED solution:

  • To change the namespace of Guzzle in your package and installed guzzle 6 too. (example: use GuzzleHttp\ => 'use GuzzleHttpSix\')

This happens cause there is a conflict in namespace used (witch is the same for guzzle 5 & 6). And Prestashop gives priority to its packages.

MustaphaC
  • 11
  • 2
-3

You can just use "guzzlehttp/guzzle": "~5.0", in your module composer.json file and you the same version which uses prestashop.

Alexander Dimitrov
  • 944
  • 1
  • 6
  • 17
  • No: if the OP uses another module that depends on Guzzle v6, there is no way to require another version in the own module – Nico Haase Mar 08 '19 at 13:20