*/ protected $dontFlash = [ 'current_password', 'password', 'password_confirmation', ]; /** * 统一的响应格式 */ private function formatJsonResponse(int $code, string $message, int $httpCode = 200, array $data = null): \Illuminate\Http\JsonResponse { return response()->json([ 'code' => $code, 'message' => $message, 'data' => $data, ], $httpCode); } /** * 统一的日志记录 */ private function logException(Throwable $e, string $level = 'error', array $extra = []): void { $context = [ 'exception' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString(), 'url' => request()->fullUrl(), 'method' => request()->method(), 'ip' => request()->ip(), 'user_agent' => request()->userAgent(), 'user_id' => auth()->id(), ...$extra ]; Log::{$level}($e->getMessage(), $context); } /** * Register the exception handling callbacks for the application. */ public function register(): void { // 记录所有异常到数据库(异步) $this->reportable(function (Throwable $e) { // 预处理请求数据,确保可以被 JSON 序列化 $requestData = [ 'url' => request()->fullUrl(), 'method' => request()->method(), 'params' => json_decode(json_encode(request()->all(), JSON_INVALID_UTF8_SUBSTITUTE), true) ?? [], 'headers' => array_map(function ($item) { return is_array($item) ? implode(', ', $item) : $item; }, request()->headers->all()), ]; // 异步分发任务 AsyncExceptionRecorder::dispatch( get_class($e), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString(), $requestData, // 使用处理过的数据 auth()->id() ); // 记录日志 if ($e instanceof ValidationException) { $this->logException($e, 'info'); } else { $this->logException($e); } }); // 404异常 $this->renderable(function (NotFoundHttpException $e) { return $this->formatJsonResponse(404, '请求的资源不存在', Response::HTTP_NOT_FOUND); }); // 模型未找到异常 $this->renderable(function (ModelNotFoundException $e) { return $this->formatJsonResponse(404, '请求的数据不存在', Response::HTTP_NOT_FOUND); }); // CSRF Token异常 $this->renderable(function (TokenMismatchException $e) { return $this->formatJsonResponse(419, 'CSRF Token 已过期,请刷新页面重试', 419); }); // 认证异常 $this->renderable(function (AuthenticationException $e) { return $this->formatJsonResponse(401, '请先登录', Response::HTTP_UNAUTHORIZED); }); // 验证异常 $this->renderable(function (ValidationException $e) { return $this->formatJsonResponse(Response::HTTP_UNPROCESSABLE_ENTITY, $e->validator->errors()->first(), 200); }); // HTTP异常 $this->renderable(function (HttpException $e) { return $this->formatJsonResponse($e->getStatusCode(), $e->getMessage(), 200); }); // 业务异常 $this->renderable(function (ApiException $e) { return $this->formatJsonResponse($e->getCode() ?: 400, $e->getMessage()); }); // 其他所有异常 $this->renderable(function (Throwable $e) { if (config('app.debug')) { throw $e; } return $this->formatJsonResponse(500, '服务器内部错误', Response::HTTP_INTERNAL_SERVER_ERROR); }); } /** * 渲染异常,所有异常都返回 统一的JSON 格式 * @param mixed $request * @param \Throwable $exception * @return mixed|Response|\Illuminate\Http\JsonResponse */ public function render($request, Throwable $exception) { if ($request->expectsJson()) { if ($exception instanceof Exception) { return response()->json([ 'code' => $exception->getCode() ?: 500, 'message' => $exception->getMessage(), 'data' => null, ], status: Response::HTTP_INTERNAL_SERVER_ERROR); } } return parent::render($request, $exception); } }