它可能不是最佳实践,但在
PHP中我们可以在文件底部定义类但是,
$t = new Test(); $t->foo(); class Test extends FakeInvalidClass { public function foo(){ echo "arrived in foo."; } }
致命错误:第4行/mysite/test.PHP中未找到“测试”类
这很奇怪……类’Test’在文件的底部定义,PHP应该失败,因为找不到FakeInvalidClass,而不是Test
<?PHP // test.PHP class Test extends FakeInvalidClass { public function foo(){ echo "arrived in foo."; } } $t = new Test(); $t->foo();
产生更人性化的错误
致命错误:第4行的/mysite/test.PHP中找不到类’FakeInvalidClass’
作为参考,这很好用:
<?PHP // test.PHP $t = new Test(); $t->foo(); class Test { public function foo(){ echo "arrived in foo."; } }
我认为当你看到Zend Engine为每个例子生成的操作码时(对我来说无论如何)都会对你有意义.
原文链接:https://www.f2er.com/php/134581.html例1:
compiled vars: !0 = $t line # * op fetch ext return operands --------------------------------------------------------------------------------- 4 0 > EXT_STMT 1 ZEND_FETCH_CLASS :0 'Test' 2 EXT_FCALL_BEGIN 3 NEW $1 :0 4 DO_FCALL_BY_NAME 0 5 EXT_FCALL_END 6 ASSIGN !0,$1 6 7 EXT_STMT 8 ZEND_INIT_METHOD_CALL !0,'foo' 9 EXT_FCALL_BEGIN 10 DO_FCALL_BY_NAME 0 11 EXT_FCALL_END 7 12 EXT_STMT 13 ZEND_FETCH_CLASS :6 'FakeInvalidClass' 14 ZEND_DECLARE_INHERITED_CLASS $7 '%00test%2Fhome%2Fflacroix%2Ftest.PHP0x7f756fea4055','test' 12 15 > RETURN 1
正如你所看到的,#1获得了Test类,而后者又进入了#13来获取FakeInvalidClass(参见返回:6).由于后者未定义,#13失败并返回#1,这也因为Test未定义而失败.
它们(#13和#1)都将调用zend_error(如PHP源代码所示),但zend_error具有全局状态(即:错误未堆叠),因此任何后续调用都将使用新错误覆盖错误消息.所以,在伪代码中:
ZEND_FETCH_CLASS('Test') ZEND_FETCH_CLASS('FakeInvalidClass') zend_error('Class FakeInvalidClass not found') return zend_error('Class Test not found') return
例2:
compiled vars: !0 = $t line # * op fetch ext return operands --------------------------------------------------------------------------------- 4 0 > EXT_STMT 1 ZEND_FETCH_CLASS :0 'FakeInvalidClass' 2 ZEND_DECLARE_INHERITED_CLASS $1 '%00test%2Fhome%2Fflacroix%2Ftest2.PHP0x7fe2c1461038','test' 10 3 EXT_STMT 4 ZEND_FETCH_CLASS :2 'Test' 5 EXT_FCALL_BEGIN 6 NEW $3 :2 7 DO_FCALL_BY_NAME 0 8 EXT_FCALL_END 9 ASSIGN !0,$3 12 10 EXT_STMT 11 ZEND_INIT_METHOD_CALL !0,'foo' 12 EXT_FCALL_BEGIN 13 DO_FCALL_BY_NAME 0 14 EXT_FCALL_END 13 15 > RETURN 1
这里#1是一个ZEND_FETCH_CLASS’FakeInvalidClass’代码,但该类不存在,因此它返回一个FakenInvalidClass not found消息,就像它应该的那样.
例3:
compiled vars: !0 = $t line # * op fetch ext return operands --------------------------------------------------------------------------------- 4 0 > EXT_STMT 1 ZEND_FETCH_CLASS :0 'Test' 2 EXT_FCALL_BEGIN 3 NEW $1 :0 4 DO_FCALL_BY_NAME 0 5 EXT_FCALL_END 6 ASSIGN !0,'foo' 9 EXT_FCALL_BEGIN 10 DO_FCALL_BY_NAME 0 11 EXT_FCALL_END 8 12 EXT_STMT 13 NOP 13 14 > RETURN 1
Zend获取ZEND_FETCH_CLASS’测试’代码并正常执行.
这可以解释为PHP将在执行代码之前解析它在代码中遇到的第一级类.当您创建扩展另一个类或实例化对象的类定义时,将在代码中的该点为该类插入ZEND_FETCH_CLASS操作码.它实际上是懒惰初始化.
这也可以通过以下方式得到证明:
<?PHP exit; class Test extends FakeInvalidClass { public function foo(){ echo "arrived in foo."; } }
结论:
ZEND_FETCH_CLASS操作码的不同参数解释了不同的错误消息.
现在,如果你想知道为什么ZE会生成这样的操作码,它可能是一个设计选择,它可能更容易维护.但说实话,我不知道.