ExceptionHandle.php
<?php
namespace app;
use manydads\exception\BaseException;
use manydads\jwt\exception\JWTException;
use manydads\jwt\exception\JWTInvalidArgumentException;
use manydads\jwt\exception\TokenAlreadyEexpired;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use Throwable;
use manydads\enum\ExceptionEnum;
use think\facade\Log;
/**
* 应用异常处理类
* Class ExceptionHandle
* @package app
*/
class ExceptionHandle extends Handle
{
/**
* 不需要记录信息(日志)的异常类列表
* @var array
*/
protected $ignoreReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
DataNotFoundException::class,
ValidateException::class,
];
// 前端判断标识
private $code;
// Http状态码
private $httpCode;
// 返回信息
private $msg;
// 错误代码
private $errorCode;
// 返回数据
private $data;
/**
* 记录异常信息(包括日志或者其它方式记录)
* @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
{
$req = \think\facade\Request::instance();
if ($e instanceof JWTException) {
// 令牌验证错误
$this->code = 1;
$this->httpCode = 403;
$this->msg = $e->getMessage();
$this->errorCode = 1000;
} elseif ($e instanceof JWTInvalidArgumentException) {
// 令牌无效
$this->code = 1;
$this->httpCode = 403;
$this->msg = $e->getMessage();
$this->errorCode = 1000;
} elseif ($e instanceof TokenAlreadyEexpired) {
// 令牌过期
$this->code = 1;
$this->httpCode = 403;
$this->msg = $e->getMessage();
$this->errorCode = 1000;
} elseif ($e instanceof BaseException) {
//如果是自定义异常,则控制http状态码,不需要记录日志
//因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
//不应当记录日志
$this->code = $e->code;
$this->httpCode = $e->httpCode;
$this->msg = $e->msg;
$this->errorCode = $e->errorCode;
$this->data = $e->data;
} else if ($e instanceof ValidateException) {
//如果是通过调用系统验证器验证异常,则控制http状态码,不需要记录日志
//因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
//不应当记录日志
$this->code = 1;
$this->httpCode = 400;
$this->msg = $e->getError();
$this->errorCode = ExceptionEnum::PARAMETER_ERROR_CODE;
} else
{
// 系统错误异常 记录日志
$this->code = 1;
$this->httpCode = 500;
$this->msg = ExceptionEnum::SERVER_ERROR_MSG;
$this->errorCode = ExceptionEnum::SERVER_ERROR_CODE;
$this->recordErrorLog($e, $req->url());
}
$result = [
'code' => $this->code,
'msg' => $this->msg,
'error_code' => $this->errorCode,
'request_url' => $req->url()
];
if (!$this->code) {
$result['data'] = $this->data;
}
return json($result, $this->httpCode);
}
/*
* 将异常写入日志
*/
private function recordErrorLog(Throwable $e, $uri)
{
Log::channel('err')->error( PHP_EOL . 'msg :' . $e->getMessage() . PHP_EOL . 'file:' .$e->getFile()
. PHP_EOL . 'line:' .$e->getLine() . PHP_EOL . 'uri:' . $uri . PHP_EOL . 'trace:' . $e->getTraceAsString());
}
}