guzzle / promises

Promises/A+ library for PHP with synchronous support
MIT License
7.61k stars 116 forks source link

PHP 8 : TypeError: method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given #129

Closed alexdebril closed 4 years ago

alexdebril commented 4 years ago

Guzzle version(s) affected: 7.1.0 PHP version: 8.0.0-beta-4 (hint: php --version) cURL version: 7.64.0 (hint: php -i | grep cURL)

Description
Whereas it works fine with PHP <=7.4.* , using Promise to perform async calls with PHP 8.0 causes a TypeError:

TypeError: method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given

How to reproduce
The code responsible for the call can be found here: https://github.com/alexdebril/feed-io/blob/master/src/FeedIo/Async/Reader.php#L64

    public function process(iterable $requests) : void
    {
        $promises = $this->client->getPromises($requests, $this);

        (new EachPromise($promises))->promise()->wait();
    }

The bug appears while running the unit tests, here's a part of the output:

1) FeedIo\Async\ReaderTest::testProcess
TypeError: method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given

/opt/vendor/guzzlehttp/promises/src/Promise.php:151
/opt/vendor/guzzlehttp/promises/src/Promise.php:113
/opt/vendor/guzzlehttp/promises/src/EachPromise.php:223
/opt/vendor/guzzlehttp/promises/src/EachPromise.php:213
/opt/vendor/guzzlehttp/promises/src/EachPromise.php:161
/opt/vendor/guzzlehttp/promises/src/Promise.php:203
/opt/vendor/guzzlehttp/promises/src/Promise.php:156
/opt/vendor/guzzlehttp/promises/src/TaskQueue.php:47
/opt/vendor/guzzlehttp/promises/src/Promise.php:246
/opt/vendor/guzzlehttp/promises/src/Promise.php:223
/opt/vendor/guzzlehttp/promises/src/Promise.php:267
/opt/vendor/guzzlehttp/promises/src/Promise.php:225
/opt/vendor/guzzlehttp/promises/src/Promise.php:62
/opt/vendor/guzzlehttp/promises/src/EachPromise.php:101
/opt/vendor/guzzlehttp/promises/src/Promise.php:246
/opt/vendor/guzzlehttp/promises/src/Promise.php:223
/opt/vendor/guzzlehttp/promises/src/Promise.php:62
/opt/src/FeedIo/Async/Reader.php:64
/opt/tests/FeedIo/Async/ReaderTest.php:44

Possible Solution

The culprit seems to be https://github.com/guzzle/promises/blob/master/src/EachPromise.php#L247

As it calls resolve(null), Promise::settle() finally tries to evaluate method_exists(null, 'then'). A possible solution could be to test if $value is not null before using in method_exists

GrahamCampbell commented 4 years ago

Does this happen on dev-master?

GrahamCampbell commented 4 years ago

It looks like this has already been fixed. A release is scheduled for tomorrow: https://github.com/guzzle/promises/pull/123.

alexdebril commented 4 years ago

Ho great, I saw the fix when I forked the project. Thanks for your reply, let's wait until tomorrow then.