rfc:catchable-call-to-member-of-non-object

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:catchable-call-to-member-of-non-object [2014/04/27 10:58] – Let's discuss this! thekidrfc:catchable-call-to-member-of-non-object [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 1: Line 1:
  
 ====== PHP RFC: Catchable "call to a member function of a non-object" ====== ====== PHP RFC: Catchable "call to a member function of a non-object" ======
-  * Version: 1.0+  * Version: 1.1
   * Date: 2014-04-26   * Date: 2014-04-26
   * Author: Timm Friebe <thekid@php.net>   * Author: Timm Friebe <thekid@php.net>
-  * Status: Under Discussion+  * Status: Accepted
   * First Published at: https://wiki.php.net/rfc/catchable-call-to-member-of-non-object   * First Published at: https://wiki.php.net/rfc/catchable-call-to-member-of-non-object
 +
 +**Note: This RFC has been superseded by the [[https://wiki.php.net/rfc/engine_exceptions_for_php7|engine exceptions]] proposal.**
  
 ===== Introduction ===== ===== Introduction =====
Line 42: Line 44:
 This behavior is consistent with how type hints work. Framework authors can turn this into exceptions if they wish. This behavior is consistent with how type hints work. Framework authors can turn this into exceptions if they wish.
  
-==== Example ====+==== Example: Exceptions ====
 The following error handler could be embedded into frameworks: The following error handler could be embedded into frameworks:
  
Line 65: Line 67:
 </PHP> </PHP>
  
 +==== Example: Without exceptions ====
 +This could be a way for people preferring not to use exceptions and instead to exit the script directly, but get a stacktrace instead of just the fatal error message:
 +
 +<PHP>
 +set_error_handler(function($code, $message) {
 +  echo "*** Error #$code: $message\n";
 +  debug_print_backtrace();
 +  exit(0xFF);
 +}, E_RECOVERABLE_ERROR);
 + 
 +$m= new some_db_model();
 +$row= $m->find(42); // null, deleted concurrently
 +$row->delete();
 +</PHP>
  
 ==== Differences from Past RFCs ==== ==== Differences from Past RFCs ====
 This proposal doesn't go as far as the controversial RFC [[engine_exceptions|RFC: Engine exceptions]]. This proposal doesn't go as far as the controversial RFC [[engine_exceptions|RFC: Engine exceptions]].
 +
 +==== Inner workings ==== 
 +
 +Taken this code:
 +
 +<PHP>
 +function a($comparator) {
 +  $result= $comparator->compare(1, 2);
 +  // ...
 +}
 +</PHP>
 +
 +You can unwind this to something like:
 +
 +  function a($comparator) {
 +    1: ZEND_INIT_METHOD_CALL $comparator 'compare'
 +    2: ZEND_SEND_VAL         1
 +    3: ZEND_SEND_VAL         2
 +    4: ZEND_DO_FCALL_BY_NAME
 +    5: ZEND_ASSIGN           $result
 +    // ...
 +  }
 +
 +The handling on checking whether the method is callable happends inside
 +the opline #1 (''ZEND_INIT_METHOD_CALL''). The opcode handler for it 
 +checks its first argument (here: ''$comparator'') whether it is an object
 +or not. In case it's not, the following happens:
 +
 +  - A recoverable error is triggered. Should the script exit here, there's nothing more to be done, this is just as it was before.
 +  - In case the script continues, all the oplines are skipped until we find the ''FCALL_BY_NAME'' opcode. This is comparable to jumping forward just as, e.g., the ''ZEND_JMP'' instruction would.
 +  - The return value is set to ''ZVAL_NULL()''.
 +  - The control is handed back to the executor, which then continues with the ''ASSIGN'' opcode
 +  - The engine is again in full control; if an exception was raised by the handler, that leads to the known behavior.
  
 ===== Other Impact ===== ===== Other Impact =====
Line 96: Line 145:
  
   * Also allowing to catch and handle other fatal errors   * Also allowing to catch and handle other fatal errors
 +
 +===== Vote =====
 +Voting started 2014-06-29 and ended 2014-07-30. 
 +
 +<doodle title="Catchable Call to a member function bar() on a non-object" auth="thekid" voteType="single" closed="true">
 +   * Yes
 +   * No
 +</doodle>
 +
  
 ===== References ===== ===== References =====
Line 101: Line 159:
   * PHP Bug [[https://bugs.php.net/bug.php?id=54195|54195]] - related, motivates necessity   * PHP Bug [[https://bugs.php.net/bug.php?id=54195|54195]] - related, motivates necessity
   * HHVM [[https://github.com/facebook/hhvm/blob/master/hphp/test/quick/method-non-object.php.expectf|throws a BadMethodCallException]] in these situations    * HHVM [[https://github.com/facebook/hhvm/blob/master/hphp/test/quick/method-non-object.php.expectf|throws a BadMethodCallException]] in these situations 
 +  * [[http://news.php.net/php.internals/73814|Mailing list announcement]] 
 +  * [[rfc/returntypehinting|Return type hinting RFC]] - related work: Some fatal errors can be prevented by setting return types.
rfc/catchable-call-to-member-of-non-object.1398596302.txt.gz · Last modified: 2017/09/22 13:28 (external edit)