You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 11:22:40