php的错误异常处理

php的错误异常机制

当我们没有自定义错误异常处理函数,php会按照默认的方式处理和显示错误异常。

自定义默认的错误异常处理函数

//注册捕获错误的处理函数
set_error_handler([__CLASS__, 'appError']);
//注册捕获错误的处理函数
set_exception_handler([__CLASS__, 'appException']);
//程序结束后执行的函数,可以获取到进程最后一个错误,方便上面两种方式没有触发的情况下处理错误
register_shutdown_function([__CLASS__, 'appShutdown']);

不同的php版本对错误和异常的捕获有不同,php7以上版本,几乎所有的错误和异常都可以被set_exception_handler注册的函数捕获。

错误异常处理函数

public static function appException($e)
{
​
        if (!$e instanceof \Exception) {
            $e = new ThrowableError($e);
        }
        //把错误信息写入到log文件
        self::getExceptionHandler()->report($e);
​
        if (PHP_SAPI == 'cli') {
            self::getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
        } else {
            //把错误信息写入到tmpl模板,发送给客户端
            self::getExceptionHandler()->render($e)->send();
        }
}

一定要接受一个参数$e,这是一个异常对象。它保存了错误的种类,行号,等等信息。我们处理错误异常就是根据这个对象来处理的。而且我们可以判断$e是属于哪个异常类,从而进行不同的处理。

tp5.1使用think\exception\handle类来处理异常的显示,比如report,render等等处理,我们就可以修改这个handle类的方法,来自定义显示错误。

php内置异常类的了解

实际上php内置了很多异常类, Error 类 和 Exception 类 都继承自 Throwable 接口,而这连个类下面又有很多子类,不同的php版本子类可能不一样,比如下面

Error
   ParseError
   TypeError
      ArgumentCountError
Exception
   RuntimeException
      PDOException
    
php7以上ParseError继承Exception,所有说大部分异常都继承Exception

分析一下Exception类

Exception {
/* 属性 */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* 方法 */

这个类的介绍可以查看php的手册,已经内置了很多方法。php为什么会内置这么多异常呢?主要是因为不同的错误和异常,php都会产生对应的异常类抛出。所以我们的异常处理函数要保证所有的异常都能处理。

自定义异常类,手动抛出异常类

有时候我们需要根据自己的需求,可以创建自定义异常类,只要继承php内置的异常类即可。比如tp5.1框架的HttpException异常

class HttpException extends \RuntimeException
{
    private $statusCode;
    private $headers;
​
    public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = [], $code = 0)
    {
        $this->statusCode = $statusCode;
        $this->headers    = $headers;
        parent::__construct($message, $code, $previous);
    }
}

只是多加了两个属性$statuCode,$header。我们手动抛出这个异常的时候,就要多传这些数据进去,然后手动抛出

扫描二维码关注公众号,回复: 12890779 查看本文章
throw new HttpException(404, 'controller not exists:'); //手动抛出异常

有了这两个信息,我们再处理异常的时候就可以先判断获取的异常是属于哪个异常类,然后再根据不同的异常显示不同的信息。

php异常处理原理

在一个进程中,异常的抛出可以是php发现错误和异常自动抛出对应的异常对象,也可以我们手动抛出异常实例。抛出后代码将不再往下执行,而是执行异常处理函数,执行完捕获异常的函数,进程就会终止。

异常抛出后,最会执行最先捕获异常的那个函数。比如代码中写了try..catch{},如果在catch已经捕获了异常,就不会让set_exception_handler注册的函数捕获了。

register_shutdown_function注册的函数在进程结束的时候都会执行,关于这个函数可以查找php手册,我们只是恰好可以在里面处理一些非常特殊的问题(有些问题php可能不会抛出异常)。在这个函数中可以通过error_get_last()得到进程失败的问题。

public static function appShutdown()
    {
        if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) {
            // 将错误信息托管至think\ErrorException
            $exception = new ErrorException($error['type'], $error['message'], $error['file'], $error['line']);
            self::appException($exception);
        }
        // 写入日志
        Container::get('log')->save();
    }

猜你喜欢

转载自blog.csdn.net/littlexiaoshuishui/article/details/103895932