12
votes

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.

5
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
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

5 Answers

1
votes

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.

0
votes

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.

0
votes

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.

-1
votes

The question does not specify what the main goal is. If your main goal is to update Prestashop (and not to solve the specific error), then I suggest that you create a local installation of the Prestashop environment - and use this to update your production environment manually, file-by-file. I can be done in the following way:

  1. Create a fresh Prestashop installation in the intended version (1.7.5?) on your local computer (use a new database). Composer will ensure that the two installations use the same dependencies.

  2. Backup your production database, and restore it on a local database server.

  3. Reconfigure the local Prestashop to talk to local database.

  4. Upgrade the local Prestashop. Check that this updated installation works.

  5. Compare the local installation with the remote installation using a diff tool (for instance, Beyond Compare). Any differences between the two installations needs to be handled case-by-case:

    • Copy new / updated code from the local installation to the remote installation.
    • Remove any obsolete files from the remote installation.
  6. Update the production database.

Remember to make a backup of the software and database before you begin.

-3
votes

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