加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

为什么PHP会为这两种情况输出不同的错误消息?

发布时间:2020-12-13 18:06:26 所属栏目:PHP教程 来源:网络整理
导读:它可能不是最佳实践,但在 PHP中我们可以在文件底部定义类但是, $t = new Test();$t-foo();class Test extends FakeInvalidClass { public function foo(){ echo "arrived in foo."; }} 生成错误消息: 致命错误:第4行/mysite/test.php中未找到“测试”类 这
它可能不是最佳实践,但在 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为每个例子生成的操作码时(对我来说无论如何)都会对你有意义.

例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会生成这样的操作码,它可能是一个设计选择,它可能更容易维护.但说实话,我不知道.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读