发布于2026-07-11 阅读(0)
扫一扫,手机访问
Lara vel 软删除默认排除已删数据,withTrashed()可临时包含,onlyTrashed()仅查已删数据;关系查询需显式调用withTrashed(),全局强制开启会破坏软删除语义。

withTrashed() 是开关Lara vel 的软删除本质上不是“删了”,而是给记录贴上一个 deleted_at 时间戳作为隐藏标记。所以常规查询(get()、find()、包括关系查询)都会被自动加上 WHERE deleted_at IS NULL 这个条件——那些被软删的记录就像直接从业务视野里消失了一样,你根本看不到它们。
想临时把它们拉回来?必须主动调用 withTrashed():
App\Models\Post::withTrashed()->where('id', 123)->first();
这个方法会临时移除 deleted_at IS NULL 的限制,但其他 where 条件照常生效。关键点:它只对当前这一条链式调用有效,不影响后续其他操作。换句话说,这就是一个“单次通行证”。
onlyTrashed() 只查已删数据,别和 withTrashed() 搞混如果需要专门处理回收站场景(比如列出所有已删除的文章),onlyTrashed() 才是正确的工具。它的作用刚好反过来——把查询条件变成 WHERE deleted_at IS NOT NULL:
App\Models\Post::onlyTrashed()->get(); // 返回所有软删的 Post
withTrashed() = “正常查 + 顺带把已删的也查出来”onlyTrashed() = “只看已删的,未删的完全不关心”withTrashed()->onlyTrashed() 会导致不可预知的行为甚至报错bootSoftDeletes() 逻辑withTrashed() 就查不到软删关联项软删除的过滤还会穿透到 Eloquent 关系里。举个例子:一个 User 有多个 Post,其中某个 Post 被软删了:
$user->posts; // 默认查不到那个软删的 Post
要让它可见,有两种方式。第一种是在定义关系时直接声明允许包含已删数据:
public function posts(){
return $this->hasMany(Post::class)->withTrashed();
}
第二种是临时在调用时加上:
$user->posts()->withTrashed()->get();
几点注意事项:
withTrashed(),就算父模型本身使用了软删除,子模型依然会被过滤掉withTrashed() 必须加在关系构造器返回的 Builder 实例上(即 posts() 这个方法),不能加在模型实例上with('posts')),同样需要在关系定义里提前声明,否则预加载时照样会丢掉软删项withTrashed() 很危险有些开发者图省事,想在模型层面一劳永逸地看到所有数据,于是在 boot() 里偷偷塞一个全局作用域强制带上 withTrashed():
protected static function booted(){
static::addGlobalScope('force-with-trashed', function (Builder $builder) {
$builder->withTrashed();
});
}
这种做法非常危险。它会让所有查询——包括后台管理、统计报表、API 接口——统统绕过软删除逻辑,极易导致数据误展示或权限越界。
软删除从来不是简单的开关,而是一层语义约束。哪条缝该打开、开多久、谁有权开——这些得由调用方自己拿捏,模型只负责守好那道 deleted_at 的门。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8