PHP: Calling Methods on Non-Objects
As an example I’m using this piece of nonsense which just sets $a
to be a number and then attempts to call a method on it:
<?php require __DIR__ . "/../../vendor/autoload.php"; use GuzzleHttp\Client; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Exception\RequestException; class DocumentTest extends \PHPUnit\Framework\TestCase { public function setUp() { // create the first request to check we can connect, can be added to // the mocks for any test that wants it $couchdb1 = '{"couchdb":"Welcome","version":"2.0.0","vendor":{"name":"The Apache Software Foundation"}}'; $this->db_response = new Response(200, [], $couchdb1); // offer a use_response for when selecting this database $egdb1 = '{"db_name":"egdb","update_seq":"0-g1AAAABXeJzLYWBgYMpgTmEQTM4vTc5ISXLIyU9OzMnILy7JAUklMiTV____PyuRAY-iPBYgydAApP5D1GYBAJmvHGw","sizes":{"file":8488,"external":0,"active":0},"purge_seq":0,"other":{"data_size":0},"doc_del_count":0,"doc_count":0,"disk_size":8488,"disk_format_version":6,"data_size":0,"compact_running":false,"instance_start_time":"0"}'; $this->use_response = new Response(200, [], $egdb1); $create = '{"ok":true,"id":"abcde12345","rev":"1-928ec193918889e122e7ad45cfd88e47"}'; $this->create_response = new Response(201, [], $create); $fetch = '{"_id":"abcde12345","_rev":"1-928ec193918889e122e7ad45cfd88e47","noise":"howl"}'; $this->fetch_response = new Response(200, [], $fetch); } /** * @expectedException \PHPCouchDB\Exception\DocumentConflictException */ public function testDeleteConflict() { $delete = '{"error":"conflict","reason":"Document update conflict."}'; $delete_response = new Response(409, [], $delete); $mock = new MockHandler([ $this->db_response, $this->use_response, $this->create_response, $this->fetch_response, $delete_response ]); $handler = HandlerStack::create($mock); $client = new Client(['handler' => $handler]); // userland code starts $server = new \PHPCouchDB\Server(["client" => $client]); $database = $server->useDB(["name" => "egdb"]); $doc = $database->create(["noise" => "howl", "id" => "abcde12345"]); $result = $doc->delete(); } }
This doesn’t work but the exact output varies between versions of PHP.
In PHP 5.5 (and maybe earlier, I don’t seem to have any of the dead versions compiled on this machine for some reason), the error message reads like this:
Fatal error: Call to a member function grow() on a non-object in /home/lorna/.../method_non_object.php on line 7
So far, so familiar.
In PHP 5.6 the error message got a bit more specific and tells us what kind of a non-object we’re dealing with:
PHP Fatal error: Call to a member function grow() on integer in /home/lorna/.../method_non_object.php on line 7
However in PHP 7, everything changes. Look at the error message output by the exact same sample code:
Fatal error: Uncaught Error: Call to a member function grow() on integer in /home/lorna/.../method_non_object.php:7
This message looks completely different because PHP 7 has a whole new way of handling errors. Not every part of PHP has switched over to the new way but it’s both excellent and quite a big change. The clue in the message which starts with the word “Uncaught”. Usually we’d expect the next word to be “Exception” but in PHP 7 there is a new Error
object, which can be intercepted using the catch
construct that we’re already familiar with.
I’ll write more about the errors in PHP 7 in a separate post but in the meantime you can read more about them in the manual (this might be my favourite manual page URL): http://php.net/error
Appears the error is also different between individual unstable versions of PHP 7 and HHVM.
https://3v4l.org/uVfc0
Pingback: PHP Annotated Monthly – November 2015 | JetBrains PhpStorm Blog