php教程,set_error_handler()如何分级别截获错误消息?
发布于 作者:苏南大叔 来源:程序如此灵动~苏南大叔在很久之前写过两篇关于set_error_handler()
的文章,这里以新的测试环境(php@8
)来重新描述这个错误信息截获处理函数set_error_handler()
。值得特别说明的是:set_error_handler()
不能处理异常exception
,能处理error
、notice
、warning
、deprecated
。
苏南大叔的“程序如此灵动”技术博客,记录苏南大叔和计算机代码的故事。本文测试环境:win10
,nginx@1.15.11
,php@8.2.10-nts
。
配置显示错误
老生常谈,记得开启php.ini
里面的显示错误的相关选项:
display_errors=On
display_startup_errors = On
error_reporting = E_ALL & ~E_NOTICE
实在不行,就在php
代码顶部加上:
error_reporting(E_All);
参考文章:
触发自定义错误
程序员可以在代码中,使用trigger_error()
来触发自定义错误信息,并根据实际情况对当前的错误信息进行评级。不传递错误的级别的话,就是默认的错误程度最轻的notice
。(很有可能系统都不处理的那种)
共有四种trigger_error()
可以触发的错误类型:E_USER_ERROR
、E_USER_WARNING
、E_USER_NOTICE
、E_USER_DEPRECATED
。
范例如下:
trigger_error("触发Error", E_USER_ERROR); // 256,fatal error,会停止执行
trigger_error("触发Warning", E_USER_WARNING); // 512
trigger_error("默认触发Notice"); // 1024
trigger_error("触发Notice", E_USER_NOTICE); // 1024
trigger_error("触发Deprecated", E_USER_DEPRECATED); // 16384
参考文章:
这里还是要特别强调一下,E_USER_ERROR
类型的错误信息,会引发fatal error
,程序会停止执行。
捕获自定义错误
在上一篇文章里面,也提到了这种trigger_error()
触发的错误信息,是不能被try catch
所捕获的。想捕获的话,需要使用set_error_handler()
来进行捕获。测试代码:
set_error_handler("customError");
function customError() {
var_dump(func_get_args());
}
trigger_error("触发Error", E_USER_ERROR);
restore_error_handler();
trigger_error("再次触发Error,不会进入自定义错误处理逻辑了", E_USER_ERROR);
这里一共使用了两个类似的函数:
set_error_handler()
设置错误处理逻辑。restore_error_handler()
重置上述逻辑。
上面的代码输出是:
array(4) {
[0]=>
int(256)
[1]=>
string(11) "触发Error"
[2]=>
string(40) "C:\Users\sunan\Desktop\test\php\test.php"
[3]=>
int(6)
}
<br />
<b>Fatal error</b>: 再次触发Error,不会进入自定义错误处理逻辑了 in <b>C:\Users\sunan\Desktop\test\php\test.php</b> on line <b>8</b><br />
定义匿名函数
苏南大叔个人觉得,这个错误逻辑处理的逻辑函数,使用匿名函数更加方便一些。比如:
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
echo "<b>出错了,错误如下:</b><br/><br/>";
echo "代码: $errno <br />\n";
echo "信息: $errstr <br />\n";
echo "文件: $errfile <br />\n";
echo "行号: $errline <br />\n";
return false; // 显示系统处理的错误逻辑
// return true; // 不显示系统处理的错误逻辑
});
// trigger_error("自定义错误", E_USER_ERROR);
trigger_error("自定义错误");
echo "next";
输出:
出错了,错误如下:
代码: 1024
信息: 自定义错误
文件: C:\Users\sunan\Desktop\test\php\test.php
行号: 12
Notice: 自定义错误 in C:\Users\sunan\Desktop\test\php\test.php on line 12
next
返回值的重要意义
在set_error_handler()
的handler()
函数里面,return true
和return false
是有非常大的区别的。
- 【推荐】
return true
或者什么都不return
,则不会转入系统处理程序。 - 【不推荐】
return false
则会转入系统处理(会输出错误信息)。但是,fatal error
会停止执行,非fatal error
不会停止执行。实质上处理了两次错误,一个是自定义的handler()
,另外一个是系统自带的错误处理逻辑。
捕获非trigger_error()其它错误
值得特殊说明的是:set_error_handler()
只能捕获trigger_error()
的错误,其它的错误信息是不能捕获的。例如:
throw new Error('错误error');
throw new Exception('异常Exception');
按级别捕获错误
在本文的开头也说过了,trigger_error()
发出的错误共有四种,那么,set_error_handler()
是可以分级别进行处理的。加上,set_error_handler()
可以捕获其它种类的错误,所以理论上可以这么定义:
set_error_handler(function () {
//...
}, E_USER_ERROR);
set_error_handler(function () {
//...
}, E_USER_NOTICE);
set_error_handler(function () {
//...
}, E_USER_WARNING);
set_error_handler(function () {
//...
}, E_USER_DEPRECATED);
理论上上述代码是可以执行的,实际的测试过程中,只要set_error_handler()
的数量多于两个,结果就变得不可控了。可能是php
的bug
。所以,目前还是推荐大家只设置一个不带error_level
参数的set_error_handler()
。然后在对应的handler()
里面对第一个参数$errno
,也就是错误级别进行switch()
操作。
set_error_handler(function() {
$code = func_get_arg(0);
echo $code,PHP_EOL;
switch($code){
case E_USER_ERROR:
break;
case E_USER_WARNING:
break;
case E_USER_NOTICE:
break;
case E_USER_DEPRECATED:
break;
default:
echo $code;
break;
}
// return true; // 尽量就别return false了...
// return false; // error 遇到 false 会停止执行
});
trigger_error("触发Error", E_USER_ERROR); // 256
trigger_error("触发Warning", E_USER_WARNING); // 512
trigger_error("默认触发Notice"); // 1024
trigger_error("触发Notice", E_USER_NOTICE); // 1024
trigger_error("触发Deprecated", E_USER_DEPRECATED); // 16384
// throw new Error('错误error'); // 不能捕获
// throw new Exception('异常Exception'); // 不能捕获
echo "next";
相关文章
- https://newsn.net/say/php-set_error_handler.html
- https://newsn.net/say/php-set_error_handler-2.html
- https://newsn.net/say/php-set_error_handler-3.html
- https://www.php.net/manual/zh/function.set-error-handler.php
结束语
set_error_handler()
的文章,没想到写了这么多篇了。真是老瓶装新酒啊,装了一遍又一遍。更多苏南大叔的php
相关文章,请点击苏南大叔的系列文章链接:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。