ThinkPHP 5 (三):构建全局异常处理层

一:为什么要做全局异常处理?

   

    全局异常的重要性 体现了AOP 切面编程  是一种思想站在一个更高的角度,用比较抽象的方式,统一的、总体的处理问题。


    ThinkPHP %提供了全局异常处理类,我们想控制返回到客户端错误信息的格式,我们就要重写全局异常类 管理这些异常 统一处理,处理异常的时候,并不会把每个异常分散到每个代码里面,而是提供了一个类似横切面的东西,render方法,这个方法会统一处理异常类信息,对使用者说,统一的异常返回信息,对用户用好易用使用,对项目构建者来说,统一处理,易于维护,达到复用和模块化。


二:异常分类

    异常大致分为两类:1️⃣用户行为导致的异常  2️⃣服务器自身异常


    1:用户行为导致的异常

        这种通常不需要记录日志,需要向用户返回具体信息。如:没有通过验证器,没有查询到结果。        


    2:服务器自身异常

        这种通常记录日志,不向客户端返回具体原因。如:代码错误,调用外部接口错误。


三:构建全局异常处理

    1:新建一个异常基类BaseException

<?php
namespace app\lib\exception;

use think\Exception;

class BaseException extends Exception
{
    public $code = 400;
    public $msg = 'invalid parameters';
    public $errorCode = 999;

    /**
     * 构造函数,接收一个关联数组
     * @param array $params 关联数组只应包含code、msg和errorCode,且不应该是空值
     */
    public function __construct($params=[])
    {
        if (!is_array($params)) {
            return;
        }

        if (array_key_exists('code', $params)) {
            $this->code = $params['code'];
        }

        if (array_key_exists('msg', $params)) {
            $this->msg = $params['msg'];
        }

        if (array_key_exists('errorCode', $params)) {
            $this->errorCode = $params['errorCode'];
        }
    }

}


    2:自定义异常处理类 ExceptionHandler  处理两种情况下产生的异常

<?php
namespace app\lib\exception;

use think\Exception;
use think\exception\Handle;
use think\Log;
use think\Request;

/**
 * Class ExceptionHandler
 * @package app\lib\exception  重写Handle的render方法,实现自定义方法
 */
class ExceptionHandler extends Handle
{
    private $code;
    private $msg;
    private $errorCode;

    public function render(Exception $e)
    {

        if ($e instanceof BaseException) {
            //如果是自定义异常,则控制http状态码,不需要记录日志
            //因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
            //不应当记录日志
            $this->code = $e->code;
            $this->msg = $e->msg;
            $this->errorCode = $e->errorCode;
        } else {
            // 如果是服务器未处理的异常,将http状态码设置为500,并记录日志
            if (config('app_debug')) {
                // 调试状态下需要显示TP默认的异常页面,因为TP的默认页面
                // 很容易看出问题
                return parent::render($e);
            }

            $this->code = 500;
            $this->msg = 'sorry, we make a mistake ^_^';
            $this->errorCode = 999;

            $this->recordErrorLog($e);
        }

        $request = Request::instance();
        $result = [
            'msg'           => $this->msg,
            'errorCode'     => $this->errorCode,
            'request_url'   => $request->url(),
        ];
        return json($result, $this->code);
    }

    /**
     * 将异常写入日志
     * @param Exception $e
     */
    private function recordErrorLog(Exception $e)
    {
        Log::init([
            'type' => 'File',
            'path' => LOG_PATH,
            'level' => ['error'],
        ]);

        Log::record($e->getMessage(), 'error');
    }
}


    3:修改config的异常配置

时光疯子博客

   


四:使用全局异常处理

    1:新建一个MissException 继承 BaseException

<?php
namespace app\lib\exception;

/**
 * 404时抛出异常
 */
class MissException extends BaseException
{
    public $code = 404;
    public $msg = 'global:your required source are not found';
    public $errorCode = 10001;
}


    2:异常使用

    

时光疯子博客

白俊遥博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论