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

Laravel路由模型绑定自定义异常:如何返回ProductNotFoundException?

搞定Laravel路由模型绑定失败时抛自定义异常的问题

嘿,完全不用放弃路由模型绑定,只要重写异常处理器的逻辑就能完美实现你的需求!下面是具体的操作步骤:

1. 先确认自定义异常已就绪

首先确保你的ProductNotFoundException已经正确创建在app/Exceptions目录下,示例代码如下:

namespace App\Exceptions;

use Exception;

class ProductNotFoundException extends Exception
{
    public function __construct()
    {
        parent::__construct('指定的商品不存在或已被删除');
    }
}

你可以根据需求自定义异常消息,或者添加其他逻辑。

2. 重写异常处理器的render方法

打开app/Exceptions/Handler.php,我们需要在这里捕获路由模型绑定失败时Laravel抛出的默认异常,然后替换成你的自定义异常。

Laravel在路由模型绑定失败时,默认会抛出Illuminate\Database\Eloquent\ModelNotFoundException——不管是商品不存在,还是商品被软删除(因为默认路由绑定会忽略软删除记录),都会触发这个异常。我们要做的就是捕获它,判断是不是Product模型的绑定失败,再抛出自己的异常。

修改Handler类的render方法:

use App\Exceptions\ProductNotFoundException;
use Illuminate\Database\Eloquent\ModelNotFoundException;

public function render($request, Throwable $e)
{
    // 捕获模型绑定失败的默认异常
    if ($e instanceof ModelNotFoundException) {
        // 获取绑定失败的模型类
        $modelClass = $e->getModel();
        
        // 确认是Product模型的绑定失败
        if ($modelClass === \App\Models\Product::class) {
            // 抛出自定义异常
            throw new ProductNotFoundException();
        }
    }

    // 其他异常交给Laravel默认处理逻辑
    return parent::render($request, $e);
}

3. (可选)给自定义异常设置专属响应

如果你想让这个自定义异常返回特定格式的响应(比如API返回JSON,页面返回自定义404视图),可以在Handler的register方法里添加以下逻辑:

public function register()
{
    $this->renderable(function (ProductNotFoundException $e, $request) {
        // 针对API请求返回JSON响应
        if ($request->wantsJson()) {
            return response()->json([
                'message' => $e->getMessage()
            ], 404);
        }
        
        // 针对页面请求返回自定义视图
        return response()->view('errors.product-not-found', [], 404);
    });
}

额外补充:如果需要处理包含软删除的绑定场景

如果你的需求是:允许路由绑定查询软删除的商品,但在商品被软删时依然抛出自定义异常,那可以直接在Product模型里重写resolveRouteBinding方法,这样就不需要在Handler里处理了:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Exceptions\ProductNotFoundException;

class Product extends Model
{
    use SoftDeletes;

    public function resolveRouteBinding($value, $field = null)
    {
        // 查询包含软删除的商品
        $product = $this->where($field ?? $this->getRouteKeyName(), $value)
            ->withTrashed()
            ->first();

        // 商品不存在时抛异常
        if (!$product) {
            throw new ProductNotFoundException();
        }

        // 商品被软删时也抛异常
        if ($product->trashed()) {
            throw new ProductNotFoundException();
        }

        return $product;
    }
}

不过如果只是用默认的路由绑定(不查询软删除记录),那前面Handler的方法就完全够用了。

这样操作后,当访问product/{product}路由时,只要商品不存在或者被软删除,就会触发你自定义的ProductNotFoundException,完美替代Laravel的默认异常!

内容的提问来源于stack exchange,提问作者user4748790

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:37:54