代码如下,已经注册了错误处理函数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是故意写的,为什么异常都没有被处理呢?
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 这种语法级的错误,可以被捕获处理,但需要一些技巧,代码结构需要改为如下,我就不借用你的代码了:
运行结果
这样就捕捉到了。
https://segmentfault.com/a/11... 这里我讲的更全一些,感兴趣可以看下