php捕获parse error 失败?

代码如下,已经注册了错误处理函数register_shutdown_function都没有执行,很奇怪


    error_reporting(-1);
    ini_set('display_errors', 1);

    set_error_handler(function(){
        echo "error handler execute";
    }, E_ALL);

    set_exception_handler(function(){
        echo "exception handler execute";
    });

    register_shutdown_function(function(){
        echo "shutdown function execute";
    });

    try{
        0$a;
    }catch(exception $e){
        echo "catch exception";
    }finally{
        echo "finally ";
    }

执行结果:


Parse error: syntax error, unexpected '$a' (T_VARIABLE) in C:\Users\mao\Documents\php\index.php on line 18

PHP Parse error:  syntax error, unexpected '$a' (T_VARIABLE) in C:\Users\mao\Documents\php\index.php on line 18
[Finished in 0.1s]

0$a是故意写的,为什么异常都没有被处理呢?

阅读 6.1k
4 个回答

Parse error 即 E_PARSE,是说代码在语法解析时发现了错误,会报错并退出解析。

注意,现在还只是解析,代码没有被载入 Zend Engine 解释,所以你的代码还没被执行就已经报错退出了,注册的 set_error_handler / register_shutdown_function 也就没什么作用了。

要理解 PHP 去执行一个脚本的流程,语法解析 -- 解释执行 -- 结束退出。如果最基本的语法解析都没通过,会直接丢给你 E_PARSE 的错误并退出执行,也就不会开始 解释执行 了。

而且看你的代码能感觉出你对 php 的错误处理也不是很清楚。
1、set_error_handler 只能捕捉 E_WARING & E_NOTICE & E_DEPRECATED & E_USER_* & 部分 E_STRICT 级的错误。语法错误 E_PARSE 是没办法用它捕获的。
2、try ... catch 只能捕获 E_PARSE & E_ERROR 级的 ERROR (还有一些其他的,E_CORE_WARNING E_CORE_NOTICE E_COMPILE_WARNING E_COMPLE_NOTICE 等,不常见)

所以 try ... catch 和 set_error_handler 可以互补,这样就能捕获所有的常见错误了。

而且要注意,被 try ... catch 或 set_error_handler(在不返回 false 的前提下) 捕获后的错误,是不会再被 PHP 做标准错误处理,error_reporting,display_errors 都是标准错误处理的设定。即便你 error_reporting(0),关闭了 PHP 标准的错误处理监听,try ... catch 和 set_error_handler 依然能捕捉到错误,而且不会退出执行(set_exception_handler 在捕获异常后就终止执行了, try ... catch 不会)。

至于你故意写 0$a 这种语法级的错误,可以被捕获处理,但需要一些技巧,代码结构需要改为如下,我就不借用你的代码了:

<?php
// 要保证一个 try ... catch 的上下文可以运行起来
try {
    // 语法检查并不会载入并执行后续要包含的文件
    // 即便包含的文件中有语法错误 也不影响本脚本的语法检查
    // 解析无误,开始执行,执行到此处时,已经是在 try ... catch 的上下文里了
    // 在 module_has_synatx_errors.php 里你写上你的 0$a; 就好
    require_once __DIR__ . '/module_has_synatx_errors.php'
} catch (\ERROR $error) {
    // 可以捕捉 E_PARSE & E_ERROR 的错误
    var_export($error);
}
<?php
//module_has_synatx_errors.php
0$a;

运行结果

ParseError::__set_state(array(
    'message'  => 'syntax error, unexpected \'$a\' (T_VARIABLE)',
    'string'   => '',
    'code'     => 0,
    'file'     => '......\module_has_synatx_errors.php',
    'line'     => 2,
    'trace'    => array(
    ),
    'previous' => null,
))

这样就捕捉到了。

https://segmentfault.com/a/11... 这里我讲的更全一些,感兴趣可以看下

语法错误是最先被系统做出警告,属于系统级别的异常,系统一警告,整个程序根本就都没运行过。

首先要明白异常跟错误是不一样的,异常是出现正常逻辑之外的情况,而错误是指运行时出错了!一旦出现错误,整个代码就不会再执行,你的程序也就挂了。而出现异常你可以使用try catch捕获到,且程序还可以继续运行!

很明显,你的代码有语法错误,那么这段程序根本执行不了,也就是说你这里是触发了一个错误而不是异常。那么如何达到你想要的效果呢?首先就要解决语法问题,看下面代码

    error_reporting(-1);
    ini_set('display_errors', 1);

    set_error_handler(function(){
        echo "error handler execute";
    }, E_ALL);

    set_exception_handler(function(){
        echo "exception handler execute";
    });

    register_shutdown_function(function(){
        echo "shutdown function execute";
    });

    try{
        echo $a;
    }catch(exception $e){
        echo "catch exception";
    }
推荐问题
宣传栏