Laravel路由模型绑定异常:抛出NotFoundHttpException而非ModelNotFoundException
问题:Laravel路由模型绑定抛出NotFoundHttpException而非ModelNotFoundException
路由配置
Route::middleware('client')->group(function(){ Route::get('/documents/{document}', [DocumentController::class, 'get']); Route::apiResource('documents', DocumentController::class)->only('store', 'destroy'); Route::post('filter', [DocumentController::class, 'filter']); });
控制器代码
public function get(Document $document): JsonResponse|string|null { // do some stuff return response()->json([ 'code' => 404, "message" => "Some Message" ], 404); }
问题现象
- 使用数据库中存在的有效UUID访问
GET /api/documents/$uuid时一切正常 - 使用不存在的无效UUID访问时,抛出
NotFoundHttpException,而非预期的ModelNotFoundException - 手动调试
Document::findOrFail($value)时,发现该方法抛出的同样是NotFoundHttpException
解决方法
1. 理解框架默认行为
Laravel在路由模型绑定过程中,会自动将ModelNotFoundException转换为NotFoundHttpException,这是框架的默认逻辑,目的是统一404状态码的异常输出。如果需要区分"资源不存在"和"路由不存在"两种场景,需要自定义异常处理逻辑。
2. 自定义异常处理器
在app/Exceptions/Handler.php中,通过renderable方法分别处理两种异常:
use Illuminate\Database\Eloquent\ModelNotFoundException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; public function register() { // 处理模型不存在的情况 $this->renderable(function (ModelNotFoundException $e, $request) { if ($request->is('api/*')) { return response()->json([ 'code' => 404, 'message' => '请求的文档不存在' ], 404); } }); // 处理路由不存在的情况(排除由ModelNotFoundException转换而来的场景) $this->renderable(function (NotFoundHttpException $e, $request) { if (!$e->getPrevious() instanceof ModelNotFoundException && $request->is('api/*')) { return response()->json([ 'code' => 404, 'message' => '请求的路由不存在' ], 404); } }); }
3. 手动查询模型(替代路由模型绑定)
如果不想依赖框架的自动绑定转换,可以在控制器方法中手动查询并捕获ModelNotFoundException:
use Illuminate\Database\Eloquent\ModelNotFoundException; public function get(string $uuid): JsonResponse { try { $document = Document::findOrFail($uuid); } catch (ModelNotFoundException $e) { return response()->json([ 'code' => 404, 'message' => '请求的文档不存在' ], 404); } // 执行后续业务逻辑 return response()->json([ 'code' => 200, 'data' => $document ]); }
内容的提问来源于stack exchange,提问作者Vüsal Hüseynli
相关产品推荐
相关产品推荐

