3 changed files with 194 additions and 0 deletions
@ -0,0 +1,37 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare (strict_types=1); |
||||
|
|
||||
|
namespace cores\exception; |
||||
|
|
||||
|
use think\Exception; |
||||
|
|
||||
|
/** |
||||
|
* 自定义异常类的基类 |
||||
|
* Class BaseException |
||||
|
* @package cores\exception |
||||
|
*/ |
||||
|
class BaseException extends Exception |
||||
|
{ |
||||
|
// 状态码 |
||||
|
public $status; |
||||
|
|
||||
|
// 错误信息 |
||||
|
public $message = ''; |
||||
|
|
||||
|
// 输出的数据 |
||||
|
public $data = []; |
||||
|
|
||||
|
/** |
||||
|
* 构造函数,接收一个关联数组 |
||||
|
* @param array $params 关联数组只应包含status、msg、data,且不应该是空值 |
||||
|
*/ |
||||
|
public function __construct($params = []) |
||||
|
{ |
||||
|
parent::__construct(); |
||||
|
$this->status = $params['status'] ?? config('status.error'); |
||||
|
$this->message = $params['message'] ?? '很抱歉,服务器内部错误'; |
||||
|
$this->data = $params['data'] ?? []; |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,146 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare (strict_types=1); |
||||
|
|
||||
|
namespace cores; |
||||
|
|
||||
|
use Throwable; |
||||
|
use think\Response; |
||||
|
use think\response\Json; |
||||
|
use think\facade\Log; |
||||
|
use think\facade\Request; |
||||
|
use think\exception\Handle; |
||||
|
use think\db\exception\PDOException; |
||||
|
use think\exception\HttpResponseException; |
||||
|
use cores\exception\BaseException; |
||||
|
|
||||
|
/** |
||||
|
* 应用异常处理类 |
||||
|
*/ |
||||
|
class ExceptionHandle extends Handle |
||||
|
{ |
||||
|
// 状态码 |
||||
|
private int $status = 200; |
||||
|
|
||||
|
// 错误信息 |
||||
|
private string $message; |
||||
|
|
||||
|
// 附加数据 |
||||
|
public array $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 $request |
||||
|
* @param Throwable $e |
||||
|
* @return Response |
||||
|
*/ |
||||
|
public function render($request, Throwable $e): Response |
||||
|
{ |
||||
|
if ($e instanceof HttpResponseException) { |
||||
|
return $e->getResponse(); |
||||
|
} |
||||
|
// 手动触发的异常 BaseException |
||||
|
if ($e instanceof BaseException) { |
||||
|
$this->status = $e->status; |
||||
|
$this->message = $e->message; |
||||
|
$this->data = $e->data; |
||||
|
$extend = property_exists($e, 'extend') ? $e->extend : []; |
||||
|
return $this->output($extend); |
||||
|
} |
||||
|
// 系统运行的异常 |
||||
|
$this->status = config('status.error'); |
||||
|
$this->message = $e->getMessage() ?: '很抱歉,服务器内部错误'; |
||||
|
// 如果是debug模式, 输出调试信息 |
||||
|
if (is_debug()) { |
||||
|
return $this->outputDebug($e); |
||||
|
} |
||||
|
// 将运行异常写入日志 |
||||
|
$this->errorLog($e); |
||||
|
return $this->output(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 返回json格式数据 |
||||
|
* @param array $extend 扩展的数据 |
||||
|
* @return Json |
||||
|
*/ |
||||
|
private function output(array $extend = []): Json |
||||
|
{ |
||||
|
$jsonData = ['message' => $this->message, 'status' => $this->status, 'data' => $this->data]; |
||||
|
return json(array_merge($jsonData, $extend)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 返回json格式数据 (debug模式) |
||||
|
* @param Throwable $e |
||||
|
* @return Json |
||||
|
*/ |
||||
|
private function outputDebug(Throwable $e): Json |
||||
|
{ |
||||
|
$debug = [ |
||||
|
'name' => get_class($e), |
||||
|
'file' => $e->getFile(), |
||||
|
'line' => $e->getLine(), |
||||
|
'code' => $this->getCode($e), |
||||
|
'message' => $this->getMessage($e), |
||||
|
'trace' => $e->getTrace(), |
||||
|
'source' => $this->getSourceCode($e), |
||||
|
]; |
||||
|
return $this->output(['debug' => $debug]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 将异常写入日志 |
||||
|
* @param Throwable $e |
||||
|
*/ |
||||
|
private function errorLog(Throwable $e) |
||||
|
{ |
||||
|
// 错误信息 |
||||
|
$data = [ |
||||
|
'file' => $e->getFile(), |
||||
|
'line' => $e->getLine(), |
||||
|
'message' => $this->getMessage($e), |
||||
|
'status' => $this->getCode($e), |
||||
|
]; |
||||
|
// 日志内容 |
||||
|
$log = $this->getVisitor(); |
||||
|
$log .= "\r\n" . "[ message ] [{$data['status']}] {$data['message']}"; |
||||
|
$log .= "\r\n" . "[ file ] {$data['file']}:{$data['line']}"; |
||||
|
// $log .= "\r\n" . "[ time ] " . format_time(time()); |
||||
|
$log .= "\r\n" . '[ header ] ' . print_r(Request::header(), true); |
||||
|
$log .= '[ param ] ' . print_r(Request::param(), true); |
||||
|
// 如果是数据库报错, 则记录sql语句 |
||||
|
if ($e instanceof PDOException) { |
||||
|
$log .= "[ Error SQL ] " . $e->getData()['Database Status']['Error SQL']; |
||||
|
$log .= "\r\n"; |
||||
|
} |
||||
|
$log .= "\r\n" . $e->getTraceAsString(); |
||||
|
$log .= "\r\n" . '--------------------------------------------------------------------------------------------'; |
||||
|
// 写入日志文件 |
||||
|
Log::record($log, 'error'); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取请求路径信息 |
||||
|
* @return string |
||||
|
*/ |
||||
|
private function getVisitor(): string |
||||
|
{ |
||||
|
$data = [Request::ip(), Request::method(), Request::url(true)]; |
||||
|
return implode(' ', $data); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
<?php |
||||
|
declare (strict_types=1); |
||||
|
|
||||
|
namespace cores; |
||||
|
|
||||
|
// 应用请求对象类 |
||||
|
class Request extends \think\Request |
||||
|
{ |
||||
|
// 全局过滤规则 |
||||
|
protected $filter = ['my_trim', 'my_htmlspecialchars', 'filter_emoji']; |
||||
|
} |
||||
Loading…
Reference in new issue