php错误处理之set_error_handler增强版
发布于 作者:苏南大叔 来源:程序如此灵动~

在本文中,苏南大叔将对上一篇文章中的遗留问题进行进一步叙述。内容主要针对php5中,如何捕获fatal error
而展开。

当然,在php7中,您可能需要的仅仅是set_exception_handler
,用它捕获fatal error
即可,不过本文的内容,对于php7也有一定的学习借鉴意义。上一篇文章的地址是:https://newsn.net/say/php-set_error_handler.html 。
前言
在上一篇的文章中,我们可以知道,在php7中,我们可以使用set_exception_handler
和set_error_handler
,完美捕获错误信息。而在php5中,似乎不是那么的完美,总是有些fatal error
是不能捕获的。这里有个解决方案。苏南大叔称之为set_error_handler增强版
。
error的级别
在php的函数中,有个error_reporting
的函数,它规定了什么样的级别的error
才会report。从这里,我们可以知道error是有级别区别的。具体的信息可以点击这里:http://doc.php.sh/zh/function.error-reporting.html 。
而在上一篇文章中,trigger_error触发的error的级别是:notice,最后的未定义函数触发的error级别是:fatal error。那么对应的php级别名词是:notice=>E_USER_NOTICE,fatal error=>E_ERROR。具体的错误级别说明,可以点击这里查看:http://doc.php.sh/zh/errorfunc.constants.html 。
set_error_handler
不处理E_ERROR
重要的是要记住 error_types 里指定的错误类型都会绕过 PHP 标准错误处理程序, 除非回调函数返回了 FALSE。 error_reporting() 设置将不会起到作用而你的错误处理函数继续会被调用 ―― 不过你仍然可以获取 error_reporting 的当前值,并做适当处理。以下级别的错误不能由用户定义的函数来处理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT。
上述引用内容来自:http://doc.php.sh/zh/function.set-error-handler.html
苏南大叔的解读是:默认参数$error_types
,将所有的错误信息,E_ALL | E_STRICT
都默认绕过php标准错误处理程序,当且仅当回调函数返回false的时候,才会进入默认php标准错误处理程序。无视error_reporting()
的相关设置。
从这里,我们就可以理解php5中,为什么最后的“函数未定义”没有被set_error_handler
捕获了。这个“函数未定义”错误在php7中可以被set_exception_hanlder
捕获。
php5中的解决方案
php5虽然已经是过去时了,但是下面的代码还是有点借鉴意义的。
代码的原理是:在一个单独的include文件里面,定义register_shutdown_function
的回调函数,然后通过分析error_get_last()
获得fatal error
的信息,进而转向错误处理程序。当然,set_error_handler
也会跟随设置。
两者区别就在于:错误处理回调函数,如果是error_get_last()
后触发的,那么return false
或者return true
都没有意义了。因为是先触发的错误,而后进行捕获的。如果是set_error_handler
触发的,那么是先捕获错误,然后再由return false
或者return true
来决定是否触发php标准错误处理程序。
对于error_get_last()
触发的这种错误回调情况,我们需要使用error_reporting(0)
或者@
来抑止标准的错误输出。
代码如下:
error_handler.php:
index.php:


方案效果截图
通过本增强版方案,php5捕获到了fatal error(代码为1)。

结语
php错误处理,是php程序调试的关键因素之一。但是市面上的各种框架太多,调试方式也不一样。所以掌握背后的原理,就可以万变不离其宗,以不变应万变了。
更多苏南大叔的php相关经验总结,请点击这里查看:https://newsn.net/tag/php/ 。


