Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 798|回复: 0

PHP 注册错误和异常处理机制

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-7-22 16:31:06 | 显示全部楼层 |阅读模式

    注册错误和异常处理机制有三个PHP函数需要学习

    1. register_shutdown_function('Bootstrap\Library\Frame::fatalError');

    2. set_error_handler('Bootstrap\Library\Frame::appError');

    3. set_exception_handler('Bootstrap\Library\Frame::appException');

    1.register_shutdown_function 

    定义:该函数是来注册一个会在PHP中止时执行的函数

    参数说明:

    void register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] )  

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

    callback:待注册的中止回调

    parameter:可以通过传入额外的参数来将参数传给中止函数

    PHP终止情况有三种

    执行完成

    <?php  
    function test()  
    {  
        echo '这个是中止方法test的输出';  
    }  
      
    register_shutdown_function('test');  
      
    echo 'before' . PHP_EOL;  
    
    // => before  
    // => 这个是中止方法test的输出  

    注意输出的顺序,等执行完成了之后才会去执行register_shutdown_function的中止方法test  

    exit/die导致的中止

    <?php  
    function test()  
    {  
        echo '这个是中止方法test的输出';  
    }  
      
    register_shutdown_function('test');  
      
    echo 'before' . PHP_EOL;  
    exit();  
    echo 'after' . PHP_EOL;  
    
    // => before
    // => 这个是中止方法test的输出  

    后面的after并没有输出,即exit或者是die方法导致提前中止。

    发生致命错误中止

    <?php  
    function test()  
    {  
        echo '这个是中止方法test的输出';  
    }  
      
    register_shutdown_function('test');  
      
    echo 'before' . PHP_EOL;  
      
    // 这里会发生致命错误  
    $a = new a();  
      
    echo 'after' . PHP_EOL;  
    
    // => before
    // => Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12
    // => Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12  
    // => Call Stack:  
    // => 0.0020     360760   1. {main}() D:\laragon\www\php_book\test.php:0  
    // => 这个是中止方法test的输出

    后面的after也是没有输出,致命错误导致提前中止了。

    参数:第一个参数支持以数组的形式来调用类中的方法,第二个以及后面的参数都是可以当做额外的参数传给中止方法。

    <?php  
      
    class Shutdown  
    {  
        public function stop()  
        {  
            echo "这个是stop方法的输出";  
        }  
    }  
      
    // 当PHP终止的时候(执行完成或者是遇到致命错误中止的时候)会调用new Shutdown的stop方法  
    register_shutdown_function([new Shutdown(), 'stop']);  
      
    // 将因为致命错误而中止  
    $a = new a();  
      
    // 这一句并没有执行,也没有输出  
    echo '必须终止';  

    也可以在类中执行:

    <?php  
      
    class TestDemo {  
        public function __construct()  
        {  
            register_shutdown_function([$this, "f"], "hello");  
        }  
      
        public function f($str)  
        {  
            echo "class TestDemo->f():" . $str;  
        }  
    }  
      
    $demo = new TestDemo();  
    echo 'before' . PHP_EOL;  
      
    /** 
    运行: 
    before 
    class TestDemo->f():hello 
     */  
    可以多次调用 register_shutdown_function,这些被注册的回调会按照他们注册时的顺序被依次调用。
    不过注意的是,如果在第一个注册的中止方法里面调用exit方法或者是die方法的话,那么其他注册的中止回调也不会被调用。
    代码:
    <?php  
    /** 
     * 可以多次调用 register_shutdown_function,这些被注册的回调会按照他们注册时的顺序被依次调用。 
     * 注意:如果你在f方法(第一个注册的方法)里面调用exit方法或者是die方法的话,那么其他注册的中止回调也不会被调用 
     */  
      
    /** 
     * @param $str 
     */  
    function f($str) {  
        echo $str . PHP_EOL;  
      
        // 如果下面调用exit方法或者是die方法的话,其他注册的中止回调不会被调用  
        // exit();  
    }  
      
    // 注册第一个中止回调f方法  
    register_shutdown_function("f", "hello");  
      
    class TestDemo {  
        public function __construct()  
        {  
            register_shutdown_function([$this, "f"], "hello");  
        }  
      
        public function f($str)  
        {  
            echo "class TestDemo->f():" . $str;  
        }  
    }  
      
    $demo = new TestDemo();  
    echo 'before' . PHP_EOL;  
      
    /** 
    运行: 
    before 
    hello 
    class TestDemo->f():hello 
     
    注意:如果f方法里面调用了exit或者是die的话,那么最后的class TestDemo->f():hello不会输出 
     */  
    该函数的作用:
    • 析构函数:在PHP4的时候,由于类不支持析构函数,所以这个函数经常用来模拟实现析构函数
    • 致命错误的处理:使用该函数可以用来捕获致命错误并且在发生致命错误后恢复流程处理

    代码如下:

    <?php  
    /** 
     * register_shutdown_function,注册一个会在php中止时执行的函数,中止的情况包括发生致命错误、die之后、exit之后、执行完成之后都会调用register_shutdown_function里面的函数 
     * Created by PhpStorm. 
     * User: Administrator 
     * Date: 2017/7/15 
     * Time: 17:41 
     */  
      
    class Shutdown  
    {  
        public function stop()  
        {  
            echo 'Begin.' . PHP_EOL;  
            // 如果有发生错误(所有的错误,包括致命和非致命)的话,获取最后发生的错误  
            if (error_get_last()) {  
                print_r(error_get_last());  
            }  
      
            // ToDo:发生致命错误后恢复流程处理  
      
            // 中止后面的所有处理  
            die('Stop.');  
        }  
    }  
      
    // 当PHP终止的时候(执行完成或者是遇到致命错误中止的时候)会调用new Shutdown的stop方法  
    register_shutdown_function([new Shutdown(), 'stop']);  
      
    // 将因为致命错误而中止  
    $a = new a();  
      
    // 这一句并没有执行,也没有输出  
    echo '必须终止';  
    Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31  
      
    Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31  
      
    Call Stack:  
        0.0060     362712   1. {main}() D:\laragon\www\php_book\1_23_register_shutdown.php:0  
      
    Begin.  
    Array  
    (  
        [type] => 1  
        [message] => Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php:31  
    Stack trace:  
    #0 {main}  
      thrown  
        [file] => D:\laragon\www\php_book\1_23_register_shutdown.php  
        [line] => 31  
    )  
    Stop.  

    注意:PHP7中新增了Throwable异常类,这个类可以捕获致命错误,即可以使用try...catch(Throwable $e)来捕获致命错误,代码如下:

    <?php  
      
    try {  
        // 将因为致命错误而中止  
        $a = new a();  
      
        // 这一句并没有执行,也没有输出  
        echo 'end';  
    } catch (Throwable $e) {  
        print_r($e);  
        echo $e->getMessage();  
    }  

    运行:

    Error Object  
    (  
        [message:protected] => Class 'a' not found  
        [string:Error:private] =>  
        [code:protected] => 0  
        [file:protected] => C:\laragon\www\php_book\throwable.php  
        [line:protected] => 5  
        [trace:Error:private] => Array  
            (  
            )  
      
        [previous:Error:private] =>  
        [xdebug_message] =>  
    Error: Class 'a' not found in C:\laragon\www\php_book\throwable.php on line 5  
      
    Call Stack:  
        0.0000     349856   1. {main}() C:\laragon\www\php_book\throwable.php:0  
      
    )  
    Class 'a' not found  
    这样的话,PHP7中使用Throwable来捕获的话比使用register_shutdown_function这个函数来得更方便,也更推荐Throwable。
    注意:Error类也是可以捕获到致命错误,不过Error只能捕获致命错误,不能捕获异常Exception,而Throwable是可以捕获到错误和异常的,所以更推荐。
     
    总结:register_shutdown_function这个函数主要是用在处理致命错误的后续处理上(PHP7更推荐使用Throwable来处理致命错误),不过缺点也很明显,只能处理致命错误Fatal error,其他的错误包括最高错误Parse error也是没办法处理的。
     

     

     

    2.set_error_handler

    通过 set_error_handler() 函数设置用户自定义的错误处理程序,然后触发错误(通过 trigger_error()):

    <?php
     // 用户定义的错误处理函数
     function myErrorHandler($errno, $errstr, $errfile, $errline) {
         echo "<b>Custom error:</b> [$errno] $errstr<br>";
         echo " Error on line $errline in $errfile<br>";
     }
    
     // 设置用户定义的错误处理函数
     set_error_handler("myErrorHandler");
    
     $test=2;
    
     // 触发错误
     if ($test>1) {
         trigger_error("A custom error has been triggered");
     }
     ?> 

    以上代码的输出类似这样:

    Custom error: [1024] A custom error has been triggered
     Error on line 14 in C:\webfolder\test.php

    定义和用法

    set_error_handler() 函数设置用户定义的错误处理函数。

    注释:如果使用该函数,会绕过标准 PHP 错误处理程序,同时如果必要,用户定义错误程序通过 die() 终止脚本。

    注释:如果错误发生在脚本执行之前(比如文件上传时),将不会调用自定义的错误处理程序因为它尚未在那时注册。

    语法

    set_error_handler(errorhandler,E_ALL|E_STRICT);
    参数 描述
    errorhandler 必需。规定用户错误处理函数的名称。
    E_ALL|E_STRICT 可选。规定显示何种错误报告级别的用户定义错误。默认是 "E_ALL"。

    技术细节

    返回值: 包含之前定义的错误处理程序的字符串。
    PHP 版本: 4.0.1+
    PHP 更新日志:

    PHP 5.5:参数 errorhandler 现在接受 NULL

    PHP 5.2: 错误处理程序必须返回 FALSE 来显示 $php_errormsg。

    3.set_exception_handler

    设置用户定义的异常处理函数:

    <?php
    // 用户定义的异常处理函数
     function myException($exception) {
         echo "<b>Exception:</b> ", $exception->getMessage();
     }
    
     // 设置用户定义的异常处理函数
     set_exception_handler("myException");
    
    // 抛出异常
    throw new Exception("Uncaught exception occurred!");
     ?> 

    以上代码的输出类似这样:

    Exception: Uncaught exception occurred!

    定义和用法

    set_exception_handler() 函数设置用户定义的异常处理函数。

    脚本会在此异常处理程序被调用后停止执行。

    语法

    set_exception_handler(exceptionhandler);
    参数 描述
    exceptionhandler

    必需。规定当一个未捕获的异常发生时所调用函数的名称。

    注释:也可以传递一个 NULL 值用于重置异常处理函数为默认值。

    技术细节

    返回值:

    返回包含之前定义的异常处理程序的名称的字符串,或者在错误时返回 NULL。

    如果之前没有定义一个错误处理程序,也会返回 NULL。

    如果参数使用了 NULL,重置处理程序为默认状态,并且会返回一个 TRUE。

    PHP 版本: 5.0+
    PHP 更新日志:

    PHP 7.0.0:传递到 exception_handler 中的参数类型从 Exception 更改为 Throwable。

    PHP 5.5:之前,如果传递 NULL,该函数返回 TRUE。从 PHP 5.5 起返回之前的处理程序。

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 13:51 , Processed in 0.059486 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表