Laravel怎么处理异常_Laravel错误与异常捕获教程【调试】

1次阅读

应重写 handler 类的 render() 方法但保留框架默认异常处理,仅拦截业务异常;api 响应需统一 json 格式并准确设状态码;queryexception 日志需展开 getprevious() 获取详情;异步任务异常需监听 jobfailed 事件

Laravel怎么处理异常_Laravel错误与异常捕获教程【调试】

全局异常处理器怎么改才不影响框架默认行为

直接重写 AppExceptionsHandler 类里的 render() 方法是最常见做法,但别一上来就 return 一个自定义响应——laravel 默认对 ValidationExceptionNotFoundHttpException 等都做了友好处理,绕过它们会导致表单错误不显示、404 页面变白屏。

正确做法是先判断异常类型,只拦截你真要干预的:

  • instanceof 区分业务异常(比如自定义的 BusinessException)和框架异常
  • ValidationException,可调用 $exception->errors() 提取字段级错误,但别丢掉原 response()
  • 生产环境禁止输出 $exception->getTraceAsString(),开发环境也建议限制在 APP_DEBUG=true 时才暴露

API 接口里怎么统一返回错误结构

Web 页面可以跳 404 或渲染错误页,但 API 必须返回 JSON 格式且状态码准确。别在每个控制器里手动 return response()->json([...], 400),容易漏状态码或格式不一致。

推荐在 Handler@render 中集中处理:

  • 检查请求是否是 ajax 或带 Accept: application/json,用 $request->expectsJson() 判断
  • ModelNotFoundException,返回 404 + {"message": "Resource not found"},不是 500
  • 捕获 QueryException 时注意:mysql1062 Duplicate entry 是业务可预期错误,不该当 500 上报

日志里为什么看不到 SQL 错误详情

默认情况下,Laravel 把数据库异常包装成 QueryException,原始错误信息藏在 $exception->getPrevious() 里。直接记录 $exception->getMessage() 只会看到“SQLSTATE[23000]: Integrity constraint violation”,没具体字段和值。

想让日志可排查,得手动展开:

  • Handler@report 中判断 $exception instanceof QueryException
  • $exception->getPrevious()?->getMessage() 拿到底层驱动错误(如 pdo 的完整报错)
  • 注意不要把敏感参数(如密码、Token)打到日志里;DB::enableQueryLog() 仅限本地调试,线上必须关

测试环境异常页面为啥不显示变量值

即使 APP_DEBUG=true,Laravel 9+ 默认用新的 Ignition 错误页,它默认隐藏闭包变量、大型数组和对象属性,避免泄露或卡死浏览器。

需要临时查看时,有三个实际可用的点:

  • 点击错误页右上角「Show context」按钮展开当前作用域变量
  • config/app.php 中设 'debug_blacklist' => [] 清空屏蔽列表(仅限本地)
  • 更稳妥的方式是加一句 throw new Exception('Debug: ' . json_encode($someVar, 320)); 强制触发并查看

真正难处理的是异步任务里的异常——队列失败不会进 Handler@report,得单独监听 JobFailed 事件。

text=ZqhQzanResources