美文网首页
PHP系统异常(3)

PHP系统异常(3)

作者: 程序员有话说 | 来源:发表于2022-09-12 09:48 被阅读0次

    在PHP 7之前,Exception未实现Throwable接口。

    Exception {
        /* 属性 */
        protected string $message ;//异常消息内容
        protected int $code ;//异常代码
        protected string $file ;//抛出异常的文件名
        protected int $line ;//抛出异常在该文件中的行号
        /* 方法 */
        public __construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]] )
        final public getMessage ( void ) : string//获取异常消息内容
        final public getPrevious ( void ) : Throwable//返回异常链中的前一个异常
        final public getCode ( void ) : int//获取异常代码
        final public getFile ( void ) : string// 创建异常时的程序文件名称
        final public getLine ( void ) : int//获取创建的异常所在文件中的行号
        final public getTrace ( void ) : array//获取异常追踪信息
        final public getTraceAsString ( void ) : string// 获取字符串类型的异常追踪信息
        public __toString ( void ) : string//将异常对象转换为字符串
        final private __clone ( void ) : void//异常克隆
    }
    

    php7+ Error和Exception的实现基类Throwable

    Exception implements Throwable{
        /* 属性 */
        protected string $message ;//异常消息内容
        protected int $code ;//异常代码
        protected string $file ;//抛出异常的文件名
        protected int $line ;//抛出异常在该文件中的行号
        /* 方法 */
        public __construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]] )
        final public getMessage ( void ) : string//获取异常消息内容
        final public getPrevious ( void ) : Throwable//返回异常链中的前一个异常
        final public getCode ( void ) : int//获取异常代码
        final public getFile ( void ) : string// 创建异常时的程序文件名称
        final public getLine ( void ) : int//获取创建的异常所在文件中的行号
        final public getTrace ( void ) : array//获取异常追踪信息
        final public getTraceAsString ( void ) : string// 获取字符串类型的异常追踪信息
        public __toString ( void ) : string//将异常对象转换为字符串
        final private __clone ( void ) : void//异常克隆
    }
    
    

    所以在php7+中,如果既想捕获异常有需要捕获错误$e是Error和Exception的基类Throwable

    try{
        ...
    }catch ( Throwable $e){
        echo $e->getCode().'<br/>';
        echo $e->getMessage().'<br/>';
        echo $e->getLine().'<br/>';
        echo $e->getFile().'<br/>';
    }
    
    

    除了Exception之外还有Error类,这个网站列出了各个版本的错误类


    设置顶层异常处理器 (Top Level Exception Handler)

    注:set_error_handler("myError") 、set_exception_handler("myException")、register_shutdown_function("myShutdown")不仅可以接受函数,还可以接受类的方法(公开的静态方法及公开的非静态方法),但需要以数组形式传递,数组的第一个值为“类名”,第二个值为“方法名”。

    1、error_reporting()
    error_reporting() 函数设置当前脚本的错误报告级别,规定报告哪种错误。E_ALL为显示所有的错误和警告信息,类似的级别还有E_ERROR—运行时致命的错误、E_WARNING—运行时非致命的错误、E_NOTICE-—运行时的通知。

    2、set_error_handler()
    设置自定义异常函数代替默认的异常处理程序,处理没有被 try/catch 块捕获的异常。 在 exception_handler 调用后异常会中止
    用于创建运行时期间的用户自己的错误处理方法

    set_error_handler指定【自定义函数】来处理系统错误,捕获错误后把错误以异常的形式抛出。当程序出现错误的时候自动调用【此自定义函数】

    3、set_exception_handler()
    set_exception_handler 指定的自定义函数来处理用户抛出的异常,如果不是异常,就实例化ThrowableError类,将异常包装起来并抛出。

    4、register_shutdown_function()
    register_shutdown_function指定appShutdown处理超时异常。
    注册一个会在php中止时执行的函数 注册一个callback,它会在脚本执行完成或者exit()后被调用。

    set_exception_handler() 函数可设置处理所有未捕获异常的用户定义函数。(即没有用 try/catch 块来捕获的异常或者try/catch没有捕获到的)

    function myException($exception)
    {
        echo "<b>Exception:</b> " , $exception->getMessage();
    }
    
    set_exception_handler('myException');
    //使用:
    throw new Exception('Uncaught Exception occurred');
    
    

    设置顶层错误处理器set_error_handler

    设置用户自定义的错误处理函数
    E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、 E_COMPILE_ERROR、E_COMPILE_WARNING是不会被这个句柄处理的,也就是会用最原始的方式显示出来。不过出现这些错误都是编 译或PHP内核出错,在通常情况下不会发生。(也就是说如果在脚本执行前发生错误,由于在那时自定义程序还没有注册,因此就不会用到这个自定义错误处理程序)

    //自定义的错误处理方法
    function _error_handler($errno, $errstr ,$errfile, $errline)
    {
        echo "错误编号errno: $errno<br>";
        echo "错误信息errstr: $errstr<br>";
        echo "出错文件errfile: $errfile<br>";
        echo "出错行号errline: $errline<br><br>";
    }
    
    set_error_handler('_error_handler', E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误
    echo $foo['bar'];  // 由于数组未定义,会产生一个notice级别的错误
    
    //人为触发错误
    trigger_error('人为触发一个错误', E_USER_ERROR);
    trigger_error('人为触发一个错误', E_ERROR); 
    
    

    这两个错误都会被自定义的函数捕获

    错误编号errno: 8  
    错误信息errstr: Undefined variable: foo  
    出错文件errfile: D:\\phpstudy\_pro\\WWW\\www.test.com\\error.php  
    出错行号errline: 13  
    
    错误编号errno: 256  
    错误信息errstr: 人为触发一个错误  
    出错文件errfile: D:\\phpstudy\_pro\\WWW\\www.test.com\\error.php  
    出错行号errline: 16
    
    错误编号errno: 256  
    错误信息errstr: 人为触发一个错误  
    出错文件errfile: D:\\phpstudy\_pro\\WWW\\www.test.com\\error.php  
    出错行号errline: 17
    
    

    7之前一大弊端,某些错误是处理不了的
    如果错误发生在脚本执行之前(比如编译、文件上传时),将不会 调用自定义的错误处理程序因为它尚未在那时注册。

    //自定义的错误处理方法
    function _error_handler($errno, $errstr ,$errfile, $errline)
    {
        echo "错误编号errno: $errno<br>";
        echo "错误信息errstr: $errstr<br>";
        echo "出错文件errfile: $errfile<br>";
        echo "出错行号errline: $errline<br><br>";
    }
    
    set_error_handler('_error_handler', E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误
    
    foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
    
    

    结果未被自定义的函数捕获

    Fatal error: Call to undefined function foobar() in D:\phpstudy_pro\WWW\www.test.com\error.php on line 19
    
    

    使用set_error_handler()后,error_reporting ()将会失效。也就是所有的错误(除上述的错误)都会交给自定义的函数处理。
    例子:三种用法

    // 三种方法如下:  
    
    1:
    set_error_handler('NonClassFunction');  // 直接转到一个普通的函数 NonClassFunction  
    
    2:
    set_error_handler(array('CallbackClass', 'StaticFunction')); // 转到 CallbackClass 类下的静方法 StaticFunction  
    
    3: 
    $o =new CallbackClass();  
    set_error_handler(array($o, 'CallbackFunction'));  // 转到类的构造函数,
    
    //可以这样操作
    class CallbackClass {  
       function CallbackClass() {  
           set_error_handler(array(&$this, 'CallbackFunction')); // the & is important  
       }  
    
       function CallbackFunction() {  
           // refers to $this  
       }  
    }
    new CallbackClass()-> CallbackClass();
    
    

    例子2:通过触发错误并以用户自定义的程序来进行内部异常的处理

    `// error handler function  
    function myErrorHandler($errno, $errstr, $errfile, $errline)  
    {  
        if (!(error_reporting() & $errno)) {  
            // This error code is not included in error_reporting, so let it fall  
            //除非回调函数返回了FALSE,error_reporting()设置将不会起到作用
            //返回false时,转到标准PHP错误处理程序
            return false;  
        }  
    
        switch ($errno) {  
        case E_USER_ERROR:  
            echo "<b>My ERROR</b> [$errno] $errstr<br />\n";  
            echo "  Fatal error on line $errline in file $errfile";  
            echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";  
            echo "Aborting...<br />\n";  
            exit(1);  
            break;  
    
        case E_USER_WARNING:  
            echo "<b>My WARNING</b> [$errno] $errstr<br />\n";  
            break;  
    
        case E_USER_NOTICE:  
            echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";  
            break;  
    
        default:  
            echo "Unknown error type: [$errno] $errstr<br />\n";  
            break;  
        }  
    
        /* Don't execute PHP internal error handler */  
        return true;  
    }  
    
    // 测试错误处理的函数  
    function scale_by_log($vect, $scale)  
    {  
        if (!is_numeric($scale) || $scale <= 0) {  
            trigger_error("log(x) for x <= 0 is undefined, you used: scale = $scale", E_USER_ERROR);  
        }  
    
        if (!is_array($vect)) {  
            trigger_error("Incorrect input vector, array of values expected", E_USER_WARNING);  
            return null;  
        }  
    
        $temp = array();  
        foreach($vect as $pos => $value) {  
            if (!is_numeric($value)) {  
                trigger_error("Value at position $pos is not a number, using 0 (zero)", E_USER_NOTICE);  
                $value = 0;  
            }  
            $temp[$pos] = log($scale) * $value;  
        }  
    
        return $temp;  
    }  
    
    // set to the user defined error handler  
    $old_error_handler = set_error_handler("myErrorHandler");  
    
    // trigger some errors, first define a mixed array with a non-numeric item  
    echo "vector a\n";  
    $a = array(2, 3, "foo", 5.5, 43.3, 21.11);  
    print_r($a);  
    
    // now generate second array  
    echo "----\nvector b - a notice (b = log(PI) * a)\n";  
    /* Value at position $pos is not a number, using 0 (zero) */  
    $b = scale_by_log($a, M_PI);  
    print_r($b);  
    
    // this is trouble, we pass a string instead of an array  
    echo "----\nvector c - a warning\n";  
    /* Incorrect input vector, array of values expected */  
    $c = scale_by_log("not array", 2.3);  
    var_dump($c); // NULL  
    
    // this is a critical error, log of zero or negative number is undefined  
    echo "----\nvector d - fatal error\n";  
    /* log(x) for x <= 0 is undefined, you used: scale = $scale" */  
    $d = scale_by_log($a, -2.5);  
    var_dump($d); // Never reached  
    ?>`
    
    以上例程的输出类似于:
    vector a
    Array
    (
        [0] => 2
        [1] => 3
        [2] => foo
        [3] => 5.5
        [4] => 43.3
        [5] => 21.11
    )
    ----
    vector b - a notice (b = log(PI) * a)
    <b>My NOTICE</b> [1024] Value at position 2 is not a number, using 0 (zero)<br />
    Array
    (
        [0] => 2.2894597716988
        [1] => 3.4341896575482
        [2] => 0
        [3] => 6.2960143721717
        [4] => 49.566804057279
        [5] => 24.165247890281
    )
    ----
    vector c - a warning
    <b>My WARNING</b> [512] Incorrect input vector, array of values expected<br />
    NULL
    ----
    vector d - fatal error
    <b>My ERROR</b> [256] log(x) for x <= 0 is undefined, you used: scale = -2.5<br />
      Fatal error on line 35 in file trigger_error.php, PHP 5.2.1 (FreeBSD)<br />
    Aborting...<br />
    
    

    set_error_handler用来捕捉trigger_error
    set_exception_handler用来捕捉throw new Exception
    这是设定一个全局的异常处理函数,在异常没有被 try catch 处理时系统会将异常交于此函数处理异常抛出但不使用try catch处理,系统会产生一个致命错误导致脚本退出执行。
    set_exception_handler只是将没有被 try catch处理的异常进行捕捉,自定义一些友好的信息输出,并不能阻止致命错误的产生,脚本依然会退出执行。
    设置默认的异常处理程序,用于没有用 try/catch 块来捕获的异常。 在exception_handler调用后异常会中止set_error_handler 则会将用户在脚本中触发的错误拦截下来进行处理,而不再提交给系统,但它不会自动识别错误级别,我们需要手动判断是否为 ERROR 级的进行退出,还是 WARNING 或 NOTICE 级的进行提示后继续执行。

    相关文章

      网友评论

          本文标题:PHP系统异常(3)

          本文链接:https://www.haomeiwen.com/subject/rqytortx.html