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

Laravel显式模型绑定下路由指定withTrashed的实现方案

优雅解决Laravel显式模型绑定支持软删除的几种方案

针对你遇到的显式模型绑定不识别withTrashed路由选项的问题,这里有几个不用重复实现$route->allowsTrashedBindings()的优雅处理方式:

方案一:在显式绑定中直接判断路由动作

在RouteServiceProvider的显式绑定逻辑里,直接通过当前路由的动作名称来决定是否包含软删除模型。示例代码如下:

// RouteServiceProvider.php
public function boot()
{
    parent::boot();

    $this->bind('organization', function ($value) {
        $query = Organization::query();
        // 检查当前路由动作是否在允许的列表中
        if (in_array(request()->route()->getActionMethod(), ['show', 'update'])) {
            $query->withTrashed();
        }
        return $query->findOrFail($value);
    });

    // Region、Location的绑定逻辑可以复用同样的判断逻辑
}

如果三个模型的判断逻辑一致,可以封装成私有方法避免重复代码:

// RouteServiceProvider.php
private function getModelQuery($modelClass)
{
    $query = $modelClass::query();
    if (in_array(request()->route()->getActionMethod(), ['show', 'update'])) {
        $query->withTrashed();
    }
    return $query;
}

// 绑定调用示例
$this->bind('organization', function ($value) {
    return $this->getModelQuery(Organization::class)->findOrFail($value);
});

方案二:利用路由参数的自定义约束

给路由参数添加额外标识,在显式绑定里识别该标识来决定是否启用软删除查询:

  1. 修改路由定义:
// api.php
Route::apiResource('organizations', OrganizationController::class)
    ->withTrashed(['show', 'update'])
    ->parameters([
        'organizations' => 'organization:withTrashed'
    ]);
  1. 在RouteServiceProvider中处理绑定:
public function boot()
{
    parent::boot();

    $this->bind('organization', function ($value, $route) {
        $paramDefinition = $route->signatureParameters()[$route->parameterNames()[0]]->getName();
        // 检查参数是否带有withTrashed标识
        if (str_contains($paramDefinition, 'withTrashed')) {
            return Organization::withTrashed()->findOrFail($value);
        }
        return Organization::findOrFail($value);
    });
}

这种方式无需硬编码动作名称,能更灵活地控制哪些路由参数支持软删除。

方案三:自定义中间件控制模型查询作用域

创建中间件挂载到指定路由,动态给模型添加withTrashed全局作用域:

  1. 创建中间件:
// app/Http/Middleware/AllowTrashedBindings.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use App\Models\Organization;
use App\Models\Region;
use App\Models\Location;

class AllowTrashedBindings
{
    public function handle(Request $request, Closure $next)
    {
        // 给目标模型添加软删除查询作用域
        foreach ([Organization::class, Region::class, Location::class] as $model) {
            $model::addGlobalScope('withTrashed', function ($query) {
                $query->withTrashed();
            });
        }

        return $next($request);
    }
}
  1. 在Kernel.php注册中间件:
// app/Http/Kernel.php
protected $routeMiddleware = [
    // ...
    'allow.trashed' => \App\Http\Middleware\AllowTrashedBindings::class,
];
  1. 修改路由定义,给指定动作挂载中间件:
// api.php
Route::apiResource('organizations', OrganizationController::class)
    ->withTrashed(['show', 'update'])
    ->middleware(['allow.trashed'])->only(['show', 'update']);

这种方式将软删除控制逻辑与路由绑定分离,符合单一职责原则,也方便后续扩展其他模型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:17:19