Laravel路由模型绑定默认不排除软删除记录,需通过全局绑定重写、模型resolveRouteBinding方法或控制器校验来过滤。推荐前两种方式统一处理,避免手动重复判断。

默认情况下,Laravel 的路由模型绑定(包括隐式和显式绑定)**不会自动排除软删除记录**。也就是说,即使某条记录已被软删除(deleted_at 不为 null),只要 ID 或自定义字段匹配,findOrFail() 仍会查到它——因为 Eloquent 默认不应用 withTrashed(),但也不主动过滤掉软删数据,除非你显式调用 whereNull('deleted_at') 或使用 withoutTrashed()。
根本原因:默认绑定不感知软删除状态
Laravel 的 Route::model() 和隐式绑定底层都调用类似 Model::findOrFail($id) 的逻辑,而 findOrFail 本身**不检查软删除状态**,只做存在性查询。所以软删记录依然能通过绑定注入控制器,后续访问时可能报错或显示异常内容。
正确关闭软删除匹配的三种方式
根据使用场景选择合适方案:
-
方案一:全局显式绑定 + 手动校验(推荐)
在RouteServiceProvider::boot()中重写绑定逻辑,强制排除软删记录:use App\Models\Post;<br>Route::bind('post', function ($value) {<br> return Post::withoutTrashed()->findOrFail($value);<br>}); -
方案二:覆盖模型的路由键查询行为
在对应模型中重写resolveRouteBinding方法:public function resolveRouteBinding($value, $field = null)<br>{<br> return $this->unlessTrashed()->where($field ?? $this->getRouteKeyName(), $value)->firstOrFail();<br>}
这样所有对该模型的隐式/显式绑定都会自动跳过软删记录。 -
方案三:控制器内二次校验(适合临时补救)
保留默认绑定,但在控制器方法里立刻判断:public function show(Post $post)<br>{<br> if ($post->trashed()) {<br> abort(404);<br> }<br> return view('posts.show', compact('post'));<br>}
注意:别用 withTrashed() 反向解决
有人尝试在绑定中写 Post::withTrashed()->findOrFail($value),这反而会让软删记录“更易被匹配”,完全违背目标。你要的是过滤掉它们,不是加载它们。
关键是让绑定过程本身执行 withoutTrashed() 或等效逻辑,而不是依赖后续处理。前两种方式更安全、统一,避免每个控制器重复判断。



















