我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

苏南大叔在很久之前写过两篇关于set_error_handler()的文章,这里以新的测试环境(php@8)来重新描述这个错误信息截获处理函数set_error_handler()。值得特别说明的是:set_error_handler()不能处理异常exception,能处理errornoticewarningdeprecated

苏南大叔:php教程,set_error_handler()如何分级别截获错误消息? - 分级别截获错误信息
php教程,set_error_handler()如何分级别截获错误消息?(图3-1)

苏南大叔的“程序如此灵动”技术博客,记录苏南大叔和计算机代码的故事。本文测试环境:win10nginx@1.15.11php@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_ERRORE_USER_WARNINGE_USER_NOTICEE_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 truereturn false是有非常大的区别的。

  • 【推荐】return true或者什么都不return,则不会转入系统处理程序。
  • 【不推荐】return false则会转入系统处理(会输出错误信息)。但是,fatal error会停止执行,非fatal error不会停止执行。实质上处理了两次错误,一个是自定义的handler(),另外一个是系统自带的错误处理逻辑。

苏南大叔:php教程,set_error_handler()如何分级别截获错误消息? - return-false
php教程,set_error_handler()如何分级别截获错误消息?(图3-2)

苏南大叔:php教程,set_error_handler()如何分级别截获错误消息? - return-true
php教程,set_error_handler()如何分级别截获错误消息?(图3-3)

捕获非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()的数量多于两个,结果就变得不可控了。可能是phpbug。所以,目前还是推荐大家只设置一个不带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";

相关文章

结束语

set_error_handler()的文章,没想到写了这么多篇了。真是老瓶装新酒啊,装了一遍又一遍。更多苏南大叔的php相关文章,请点击苏南大叔的系列文章链接:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   php