Laravel 11中如何通过withExceptions渲染默认404页面?
在Laravel 11中实现API返回JSON 404、非API返回默认404页面
问题原因
在Laravel 11的withExceptions()闭包中直接调用abort(404)会触发嵌套异常,导致框架返回500错误,而非预期的404页面。正确的做法是直接返回响应,而非抛出新异常。
解决方案
在bootstrap/app.php的withExceptions()配置中,捕获NotFoundHttpException,根据请求类型返回对应响应:
方式一:直接渲染默认404视图
return Application::configure(basePath: dirname(__DIR__)) // 其他配置(路由、中间件等)... ->withExceptions(function (Exceptions $exceptions) { $exceptions->render(function (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e, $request) { // 识别API请求(可根据实际路由规则调整判断条件) if ($request->is('api/*') || $request->wantsJson()) { return response()->json([ 'message' => '请求的资源不存在', 'status_code' => 404 ], 404); } // 非API请求,渲染框架默认404页面 return response()->view('errors.404', [], 404); }); }) ->create();
方式二:复用框架默认异常处理逻辑
如果需要保留框架默认的错误页面行为(比如调试模式下的详细异常信息、自定义错误视图),可以直接调用框架内置的异常处理器:
return Application::configure(basePath: dirname(__DIR__)) // 其他配置(路由、中间件等)... ->withExceptions(function (Exceptions $exceptions) { $exceptions->render(function (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e, $request) { if ($request->is('api/*') || $request->wantsJson()) { return response()->json([ 'message' => '请求的资源不存在', 'status_code' => 404 ], 404); } // 调用框架默认异常处理器渲染404页面 return app(\Illuminate\Foundation\Exceptions\Handler::class)->render($request, $e); }); }) ->create();
关键说明
NotFoundHttpException是Laravel抛出404错误时的底层异常类,包括abort(404)触发的异常。- 判断API请求的条件可根据实际项目调整(比如检查请求头
Accept: application/json)。 - 避免在
render闭包中再次抛出异常(如abort(404)),否则会引发嵌套异常导致500错误。
内容的提问来源于stack exchange,提问作者Gregory Farias
相关产品推荐
相关产品推荐

