最新公告
  • 欢迎您访问爱上源码网,分享精品整站源码,网站模板,游戏源码,APP小程序源码以及视频教程免费下载;服务永无止境!立即加入我们
  • 关于PHP中Exception、Error Handler的细节以及实例详解

    前言

    最近项目中有一个功能需要实现:调试模式下, 将所有错误提前输出, 再输出页面内容.

    为实现上述功能, 需使用到Exception, Error相关Handler方法, 发现有许多坑, 故写此文与大家分享.

    推荐PHP视频教程:https://www.23ym.cn/course/list/29/type/2.html

    主要函数

    此篇文章重点关注以下几个函数

    1、error_reporting()

    2、set_error_handler()

    3、set_exception_handler()

    4、register_shutdown_function()

    5、error_get_last()

    以下本文中重点讲解问题列表:

    1、error_reporting() error_get_last() 有什么联系?

    2、set_error_handler() set_exception_handler() 绑定的handler什么时候才会启动? 它们有什么联系?

    3、register_shutdown_function()通常跟Exception/Error有关系么?

    解疑:

    1. error_reporting()error_get_last() 有什么联系?

    link: php.net - error_reporting()
    link: php.net - error_get_last()

    a:int error_reporting ([ int $level ] )

    大家应该再熟悉不过了, 因此不再赘述.

    b:array error_get_last ( void )

    获取最后发生的错误

    通常用来获取PHP运行过程中的Fatal Error错误(PHP 5).

    这两个函数在字面上关联性并不强, 但请观察以下代码及输出

    <?php
    error_reporting(E_ALL & ~E_NOTICE);
    $a = $b;  //E_NOTICEprint_r(error_get_last());/* output:
    Array
    (
        [type] => 8
        [message] => Undefined variable: b
        [file] => /app/t.php
        [line] => 3
    )
    */

    error_get_last()虽然说明了获取最后发生的错误, 实际上也是如此. 但却没有说明, 被error_reporting()忽略掉的错误是否有可能被获取到, 因此, 当我们使用error_get_last()时需要注意平时忽略掉的错误, 如: E_DEPRECATED

    2. set_error_handler()set_exception_handler() 绑定的handler什么时候才会启动? 它们有什么联系?

    link: php.net - set_error_handler()
    link: php.net - set_exception_handler()

    a、mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )

    设置用户自定义的错误处理函数

    通常在PHP脚本运行过程中, 出现一些非中断性错误时触发.
    我们会用这个来记录错误日志或直接输出等操作.

    注意:

    FALSE: 标准的错误处理依然会被执行(标准错误处理根据 display_errors = true/false 决定是否输出到stderr)

    1、参数$error_types大多设定为error_reporting(), 但建议设定为E_ALL, 具体哪些错误需要被处理, 哪些不需要, 在handler内进行判断明显更加灵活.

    2、以下级别的错误不能由用户定义的函数来处理: E_ERROR E_PARSEE_CORE_ERRORE_CORE_WARNING E_COMPILE_ERRORE_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT

    3、handler被触发后, 并不会中断PHP运行.

    4、bool error_handler ( int $errno , string $errstr [, string $errfile [, int $errline [, array $errcontext ]]] )
    注意error_handler的返回值:

    b、callable set_exception_handler ( callable $exception_handler )

    设置用户自定义的异常处理函数
    设置默认的异常处理程序,用于没有用 try/catch 块来捕获的异常。 在 exception_handler 调用后异常会中止。

    注意:

    注意点中2, 3项轻描淡写了一下PHP 5/PHP 7之间的不同却透露出重要的消息(坑..)
    PHP 7中, exception_handler 不再只接受Exception了, 并且接收了Error错误.
    link: php.net - PHP7 Errors列表

    1、exception_handler 调用后异常会中止(脚本终止).

    2、PHP 5, PHP 7的exception_handler并不相同.
    PHP 5: void handler ( Exception $ex )
    PHP 7: void handler ( Throwable $ex )

    3、自 PHP 7 以来,大多数错误抛出 Error 异常,也能被捕获。 Error Exception 都实现了 Throwable 接口。

    因此, set_error_handler() set_exception_handler() 之间的关系也迎刃而解:

    PHP 5:

    1、set_error_handler(): 负责非中断行错误.

    2、set_exception_handler(): 负责没有被catch的异常(会中断).

    3、Fatal Error等: 并不会被两者管理, 正常输出到屏幕上(弊端).

    PHP 7:

    1、set_error_handler(): 负责非中断行错误.

    2、set_exception_handler(): 负责没有被catch的异常, Error(会中断)

    3、Fatal Error等: 由set_exception_handler()管理.

    3. register_shutdown_function()通常跟Exception/Error有关系么?

    link: php.net - register_shutdown_function()

    注册一个 callback ,它会在脚本执行完成或者 exit() 后被调用。

    根据说明可以得出结论, 它与Exception/Error完全没关系.
    提出这个问题, 主要是因为, 在PHP5中Fatal Error并没有明确的接收地点, 所以我们通常配合error_get_last()来接收Fatal Error

    <?php 
    register_shutdown_function('shutdown_function');
    unknown_function();function shutdown_function() {
      print_r(error_get_last());
    }/* output:Array(
        [type] => 1
        [message] => Uncaught Error: Call to undefined function unknown_function() in /app/t.php:3Stack trace:#0 {main}
      thrown
        [file] => /app/t.php
        [line] => 3)
    */

    然而随着PHP 7的到来, Error已经可以被set_exception_handler()捕捉了, 再通过error_get_last()就多余了. shutdown中更多的是一些版本冗余的工作.

    实例

    前言中的需求: 调试模式下, 将所有错误提前输出, 再输出页面内容.
    以下是demo, 省去了环境判断(debug环境), 大家可以根据下面这段代码, 了解本文中所说的各种handler的触发和调用情况.

    <?php/*
    要求: 将所有异常打印在屏幕最上方
    *//* Fatal Error 中断脚本 -> shutdown_handler *///设置错误级别define("END_ERRORS", '--END ERRORS--' . PHP_EOL . PHP_EOL);
    ini_set('display_errors', true);
    ini_set('error_reporting', E_ALL & ~E_DEPRECATED);
    
    set_error_handler('usr_err_handler', error_reporting()); //注册错误处理函数set_exception_handler('usr_ex_handler'); //注册异常处理函数register_shutdown_function('shutdown_handler');    //注册会在php中止时执行的函数$global_errors = [];    //用于记录所有错误$errnos = [             //错误级别
        0 => 'ERROR',//PHP7 ERROR的CODE
        1 => 'E_ERROR',//FATAL ERROR(PHP5), E_ERROR
        2 => 'E_WARNING',    4 => 'E_PARSE',    8 => 'E_NOTICE',    16 => 'E_CORE_ERROR',    32 => 'E_CORE_WARNING',    64 => 'E_COMPILE_ERROR',    128 => 'E_COMPILE_WARNING',    256 => 'E_USER_ERROR',    512 => 'E_USER_WARNING',    1024 => 'E_USER_NOTICE',    2048 => 'E_STRICT',    4096 => 'E_RECOVERABLE_ERROR',    8192 => 'E_DEPRECATED',    16384 => 'E_USER_DEPRECATED',    30719 => 'E_ALL',
    ];function reset_errors(){    global $global_errors;
        $global_errors = [];
    }function get_errnostr($errno){    global $errnos;    return $errnos[$errno];
    }function set_errnos($errno, $errstr){    global $global_errors;
        $global_errors[] = [        'errno' => $errno,        'errnostr' => get_errnostr($errno),        'errstr' => $errstr,
        ];
    }function print_errors($prefix){    global $global_errors;    foreach ($global_errors as $err) {//由于handler中依然有可能有error 因此放最后
            printf("[%s]: %s, %d, %s\n",
                $prefix, $err['errnostr'], $err['errno'], $err['errstr']);
        }
    }//用户异常处理函数 (进来就中断脚本) PHP5只有Exception进来   PHP7Error和Exception//PHP7中 void handler (Throwable $ex) 可捕获Error和Exception两种异常, 暂不管//http://php.net/manual/en/language.errors.php7.php PHP7 Error阅读//内部如果有Error则触发Error函数, 再回到错误行继续执行function usr_ex_handler($ex){
        $content = ob_get_clean();  //让Exception/Error提前展示
    
        print_errors('EX ERROR');
        reset_errors();
    
        $errnostr = get_errnostr($ex->getCode());
        $errno = $ex->getCode();
        $errstr = $ex->getMessage();    if ($ex instanceof Exception) {
            printf("[EXCEPTION]: %s, %d, %s\n", $errnostr, $errno, $errstr);
        } else {//针对PHP7  $ex instanceof Error
            printf("[EX FATAL ERROR]: %s, %d, %s\n", $errnostr, $errno, $errstr);
        }    //由于handler中依然有可能有error 因此放最后
        print_errors('EX ERROR');
        reset_errors();    echo END_ERRORS;    echo $content;    return;
    }//用户错误处理函数//E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING不能被用户处理function usr_err_handler($errno, $errstr, $errfile, $errline, $errcontext){
        set_errnos($errno, $errstr);    return true;    //如果函数返回 FALSE,标准错误处理处理程序将会继续调用。}//用户PHP终止函数function shutdown_handler(){
        $content = ob_get_clean();  //让Exception/Error提前展示
        $err = error_get_last();//检查一下是否有遗漏掉的错误 php5 fatal error
        if ($err['type'] & error_reporting()) {
            set_errnos($err['type'], $err['message']);
        }
        print_errors('ST ERROR');
        reset_errors();    echo $content;
    }
    
    ob_start();echo 'Main function...', PHP_EOL;//搞事情//throw new Exception('这是一个异常');trigger_error('这是一个用户error');//E_USER_NOTICEif (version_compare(PHP_VERSION, '7.0.0') >= 0) {
        mcrypt_encrypt();//E_WARNING, E_DEPRECATED} else {
        mysql();
    }
    unknown_function(); //fatal error$content = ob_get_clean();//优先输出错误print_errors('MA ERROR');if (!empty($global_errors)) {    echo END_ERRORS;
    }
    reset_errors();//输出正文内容echo $content;

    以上就是全部内容了,更多相关问题请访问PHP中文网:https://www.23ym.cn/

    以上就是关于PHP中Exception、Error Handler的细节以及实例详解的详细内容,更多请关注爱上源码网其它相关文章!

  • 微信
  • 分享
  • 相关标签:exception
  • 本文转载于:开发者头条,如有侵犯,请联系916990011@qq.com删除
    • 上一篇:使用PHP来获取客户端和服务端IP
    • 下一篇:关于PHP安全编程的一些建议

    相关文章

    相关视频

    • php异常处理类Exception用法详解
    • 关于Python中异常(Exception)
    • 在PHP命名空间中使用Exception报错not…
    • laravel框架中TokenMismatchEx…
    • 关于PHP中Exception、Error Han…
    • —————链式操作之failException
    • failException(链式操作20)

    本文有爱上源码下载完入驻作者发布,如果对您版权造成侵害,可以联系本站站长管理进行维权删除,本站收到维权24小时内进行处理,谢谢您关注23ym.cn!
    本站分享大量程序员技术文章以及对编程开发的初级入门教程,包括图文讲解笔记和高清视频下载~

    重要声明:
    1.本站视频教程,软件及网站源码版权均属于原作者所有,您必须在下载后的24个小时之内,从您的电脑中删除!非法商业用途,后果自负!
    2.本站不保证所提供下载资源的安全性和完整性,仅供下载学习之用!如链接失效或资源含外站广告,请联系客服处理!给予奖励!
    3.本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!本站提供有偿服务!如有侵权请联系在线客服!
    4.如您手中有优质资源或教程,可以自助投稿发布,成功分享后有奖励和额外收入!
    5.如您需要正版微擎模块可联系本站客服,我们有价值30w+商业微擎应用出售微擎坑位和招收代理!
    6.400电话/软著/ICP,EDI许可证/商标特价办理中!
    爱上源码下载网 » 关于PHP中Exception、Error Handler的细节以及实例详解

    常见问题FAQ

    从网站下载的源码都有安装教程么?不会安装怎么办?
    本站发布的网站源码和模板资源大部分在压缩包内都有教程,如您不会安装可以联系本站在线技术进行付费安装。
    爱上源码的所有源码都是亲测能正常运行的么?
    本站目前拥有资源10w+,包含整站源码,网站模板,游戏源码,小程序源码,视频教程,破解软件等,每天也在测试更新;因时间和精力有限我们无法对资源进行一一测试,只能保证所分享资源内容无误,希望理解。
    我手中的优质资源可以在你这换钱或者VIP么?
    爱上源码支持投稿,欢迎发布您手中的优质资源进行售卖;本站VIP支持免费获取,目前邀请10人注册爱上源码即可免费获取VIP。
    爱上源码除了资源分享还有其他业务没?
    【价值30W+微擎模块出售正版商业微擎坑位及招收代理,详情咨询本站客服!】我们团队目前运营并推广几套商业化saas智能小程序系统能满足大部分小程序开发需求,并由SaaS和独立部署版商城小程序系统;另外销售400电话,各种ICP/EDI资质证书办理,软著和商标注册服务等。

    发表评论

    • 19会员总数(位)
    • 33905资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 300稳定运行(天)

    提供最优质的资源集合

    开通VIP 源码下载