This is an old revision of the document!
PHP RFC: Catchable "call to a member function of a non-object"
- Version: 0.8
- Date: 2014-04-26
- Author: Timm Friebe thekid@php.net
- Status: In Draft
- First Published at: https://wiki.php.net/rfc/catchable-call-to-member-of-non-object
Introduction
One of the most common fatal errors in PHP is the “call to a member function of a non-object” type. This occurs whenever a method is called on anything other than an object (usually null), e.g.:
// ...when getAction() returns null: $this->getAction()->invoke();
If you want to run PHP as a webserver itself, fatal errors are problematic. For a long story on why you would want to do that in the first place, see http://marcjschmidt.de/blog/2014/02/08/php-high-performance.html
Proposal
This proposal's essence is to turns fatal errors generated from calls to methods on a non-object into E_RECOVERABLE_ERROR
s.
set_error_handler(function($code, $message) { var_dump($code, $message); }); $x= null; var_dump($x->method()); echo "Alive\n";
The above produces the following output:
int(4096) string(50) "Call to a member function method() on a non-object" NULL Alive
Consistency
This behavior is consistent with how type hints work. Framework authors can turn this into exceptions if they wish.
This proposal adds an optional return type declaration to function declarations including closures, functions, generators, interface method declarations and class declarations. This RFC does not change the existing type declarations nor does it add new ones (see differences from past RFCs).
Example
The following error handler could be embedded into frameworks:
set_error_handler(function($code, $message) { if (0 === strncmp('Call', $message, 4)) { throw new BadMethodCallException($message); } else if (0 === strncmp('Argument', $message, 8)) { throw new InvalidArgumentException($message); } else { trigger_error($message, E_USER_ERROR); } }, E_RECOVERABLE_ERROR); $x= null; try { $x->method(); } catch (BadMethodCallException $e) { echo "Caught expected ", $e->getMessage(), "!\n"; } echo "Alive\n";
Differences from Past RFCs
This proposal doesn't go as far as the controversial RFC RFC: Engine exceptions.
Other Impact
On Backward Compatiblity
This RFC is backwards compatible with previous PHP releases.
On SAPIs
There is no impact on any SAPI.
On Existing Extensions
No impact.
On Performance
No effect, before, the script terminated.
Proposed PHP Version(s)
This RFC targets PHP 5.7 or PHP 6.0, whichever comes first.
Proposed Voting Choices
This RFC modifies the PHP language behaviour and therefore requires a two-third majority of votes.
Patches and Tests
There is a pull request available over at GitHub which includes tests. Feedback welcome!
Future Work
Ideas for future work include:
- Also allowing to catch
- Allowing nullable types(such as
?DateTime
). This is discussed in a related RFC: Declaring Nullable Types - Unifying the reflection type API by introducing a
ReflectionType
class that both parameter and return types can use. - Improving parameter variance. Currently parameter types are invariant while they could be contravariant.
- Improving runtime performance by doing type analysis.
- Updating documentation to use the new return type syntax.
References
- PHP Bugs 46601, 51882 and https://bugs.php.net/bug.php?id=51848 51848 - bugs which would be fixed by this
- PHP Bug 54195 - related, motivates necessity
- HHVM throws a BadMethodCallException in these situations