商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Laravel怎么实现模型软删除查询开关_Laravel强制包含已删数据【指南】

Laravel怎么实现模型软删除查询开关_Laravel强制包含已删数据【指南】

  发布于2026-07-11 阅读(0)

扫一扫,手机访问

让我们先把原文的核心逻辑理清楚:软删除不是真的删除,而是给记录打上 `deleted_at` 时间戳。默认查询自动过滤掉这些记录,想要找回它们就得用 `withTrashed()`、`onlyTrashed()` 这些方法。关系查询里也需要注意,全局作用域硬编码会破坏设计意图。这些点一个都不能丢,但我们可以把讲法变得像经验丰富的开发者之间的对话。 下面是改写后的完整文章,保持原有的章节层次、图片、代码块以及引用段落,只调整表达方式和节奏。
Lara vel 软删除默认排除已删数据,withTrashed() 可临时包含,onlyTrashed() 仅查已删数据;关系查询需显式调用 withTrashed(),全局强制开启会破坏软删除语义。

Lara vel怎么实现模型软删除查询开关_Lara vel强制包含已删数据【指南】

软删除模型默认不查已删数据,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() 这个方法),不能加在模型实例上
  • 如果使用了 Eager Loading(比如 with('posts')),同样需要在关系定义里提前声明,否则预加载时照样会丢掉软删项

全局作用域下硬编码 withTrashed() 很危险

有些开发者图省事,想在模型层面一劳永逸地看到所有数据,于是在 boot() 里偷偷塞一个全局作用域强制带上 withTrashed()

protected static function booted(){
    static::addGlobalScope('force-with-trashed', function (Builder $builder) {
        $builder->withTrashed();
    });
}

这种做法非常危险。它会让所有查询——包括后台管理、统计报表、API 接口——统统绕过软删除逻辑,极易导致数据误展示或权限越界。

  • 软删除的核心价值是逻辑隔离,不是存储开关;强行全局放开相当于废掉整个机制
  • 真正需要“始终可见”的字段(如日志、审计记录),应该单独建表,不走软删除模型
  • 如果某些控制器或服务类确实高频用到已删数据,建议封装成专用的 Repository 方法,而不是污染模型的全局行为

软删除从来不是简单的开关,而是一层语义约束。哪条缝该打开、开多久、谁有权开——这些得由调用方自己拿捏,模型只负责守好那道 deleted_at 的门。

本文转载于:https://www.php.cn/faq/2378766.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注