异常处理接管

本着严谨的原则,框架会对任何错误(包括警告错误)抛出异常。系统产生的异常和错误都是程序的隐患,要尽早排除和解决,而不是掩盖。对于应用自己抛出的异常则做出相应的捕获处理。

 

1.框架支持异常处理由开发者自定义类进行接管,需要在​​app​​目录下面的​​provider.php​​文件中绑定异常处理类,例如:



// 绑定自定义异常处理handle类
'think\exception\Handle' => app\exception\ApiExceptionHandle::class,


2.自定义类需要继承​​think\exception\Handle​​并且实现​​render​​方法,可以参考如下代码:



class ApiExceptionHandle extends Handle
{
/**
* 记录异常信息(包括日志或者其它方式记录)
*
* @access public
* @param Throwable $exception
* @return void
*/
public function report(Throwable $exception): void
{
// 使用内置的方式记录异常日志
parent::report($exception);
}

/**
* Render an exception into an HTTP response.
*
* @access public
* @param \think\Request $request
* @param Throwable $e
* @return Response
*/
public function render($request, Throwable $e): Response
{
$massageData = Env::get('app_debug', false) ? [
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTrace(),
'previous' => $e->getPrevious(),
] : [];

// 添加自定义异常处理机制
if ($e instanceof DbException) {
return json($e->getCode(),'数据获取失败', $massageData);
} elseif ($e instanceof AuthException || $e instanceof ValidateException || $e instanceof ApiException) {
return json($e->getCode() ?: 400, $e->getMessage());
} elseif ($e instanceof AdminException) {
return json($e->getCode(),$e->getMessage(), $massageData);
} else {
return json(400001,'未知错误');
}
}

}


上面的操作后,其实如果其他逻辑抛出异常,这个类是会响应到的. 

如果抛出  ​​throw new app\exception\cus​​Exception​​([​​​​10006,'自定义异常消息'​​​​]);//这个异常类的构造函数可以自己实现​

ApiExceptionHandle这个类是可以响应的,执行查不到这个异常,返回 json(400001,'未知错误');

 

3.现在我们实现异常类(自定义的异常类),



/**
*
* @package crmeb\exceptions
*/
class AdminException extends \RuntimeException
{
public function __construct($message, $code = 0, Throwable $previous = null)
{
if(is_array($message)){
$errInfo = $message;
$message = $errInfo[1] ?? '未知错误';
if ($code === 0) {
$code = $errInfo[0] ?? 400;
}
}

parent::__construct($message, $code, $previous);
}
}


 

4.至此,我们如果在controller或Service手动抛出异常,就会返回json



throw new app\exception\AdminException([400,'后台异常']);
//抛出后台异常,会被handle方法对应的if else处理返回json


 

5.拓展:其实这样已经可以了,如果抛异常就像第四那样写,但有时为了统一,错误的code都是统一写在一个文件,如:

ExErrorCode.php



/**
* 错误码统一存放类
* Class ExErrorCode
*/
class ExErrorCode
{
const SUCCESS = [200, 'SUCCESS'];
const ERROR = [400, 'ERROR'];
const ERR_LOGIN_INVALID = [410000, 'Landing overdue'];
//登出
const LOGIN_OUT = [410008,'登出'];
}


 

最后这样抛出异常:



throw new app\exception\AdminException(ExErrorCode::LOGIN_OUT);
//抛出后台异常,会被handle方法对应的if else处理返回json