发布于2026-07-07 阅读(0)
扫一扫,手机访问
处理API和网页请求抛异常时的响应形式,这活儿,中间件和控制器都干不了。必须得在 App\Exceptions\Handler::render() 这个核心位置来做判断。
别依赖路由前缀(比如 api/*)或者手动传参来判断。Lara vel 自己就提供了两个靠谱的方式:
$request->expectsJson():这个会检查请求头里是不是带着 Accept: application/json,或者是不是 AJAX 请求(带了 X-Requested-With: XMLHttpRequest)。现在绝大多数前端框架,像 Axios、Fetch,默认都会带上这些头信息,所以这个方法很推荐。$request->is('api/*'):这个只匹配 URL 路径,适合你明确把所有 API 都放在 /api/ 下的项目。但它有个局限,识别不了子域名或者版本前缀(比如 v1.api.example.com 这种)。if ($request->expectsJson() || $request->is('api/*')),这样既灵活,兼容性也强。如果直接写 return parent::render($request, $exception),那就走 Lara vel 的默认逻辑了。对于 API 请求来说,这意味着在调试模式下会直接暴露堆栈信息,生产环境则返回一个空白 500 页面。所以,必须提前把几种常见的异常拦截下来:
ModelNotFoundException:对应 404 错误。API 可以返回 response()->json(['message' => 'Not found'], 404),网页请求则返回 response()->view('errors.404')。ValidationException:这是 $request->validate() 抛出的异常,Lara vel 会自动捕获。API 返回 response()->json(['errors' => $exception->errors()], 422),网页可以重定向回表单并显示错误提示。AuthorizationException:权限不足,统一返回 403。无论是 API 还是网页,都建议用 JSON 格式返回,避免前端去解析一个 HTML 错误页面。Exception 或 Throwable 来做兜底处理。这会吞掉本该触发调试器的致命错误,比如内存溢出、语法错误,到时候排查问题会非常痛苦。因为异常完全可能在中间件执行之前或之后发生,中间件根本抓不到。来看看几个典型场景:
NotFoundHttpException → 这时候还没进入任何中间件。{{ $user->name }} 但 $user 是 null → 视图引擎报错 → 中间件早已执行完毕。QueryException → 这发生在模型方法内部,远早于响应构造阶段。
开发环境下,Lara vel 默认会返回一个带堆栈信息的 HTML 错误页,哪怕请求头是 Accept: application/json。解决办法是在 render() 方法的最开头加一个强制判断:
if ($request->expectsJson()) {
return response()->json([
'message' => 'Server Error',
'debug' => config('app.debug') ? $exception->getMessage() : null
], 500);
}
这里有个重要的安全提醒:在生产环境里,千万别把 $exception->getMessage() 直接返回,这很容易泄露服务器路径、数据库名等敏感信息。config('app.debug') 是唯一安全的开关依据。
最后,还有一个容易被忽略的坑:第三方 SDK 抛出的异常。比如 Stripe、PayPal 的客户端库,它们往往用的是原生的 Exception,不会自动进入你定义的 ValidationException 分支。这类异常需要手动补一层判断,或者在调用处用 try/catch 捕获后,重新 throw new CustomPaymentException(),否则它们就会悄无声息地变成 500 HTML 页面,让你花很多时间去排查。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8