db类查询不支持软删除,会查出所有记录包括已软删数据;需手动添加where('delete_time', null)等条件过滤,或改用模型查询实现软删逻辑。

因为 Db 类查询完全不支持软删除机制,它只做原生 SQL 操作,不会自动添加 delete_time IS NULL 条件,也不会读取模型里的 SoftDelete 配置。
Db 查询和软删除互不感知
Db 是底层查询构造器,面向数据库表而非模型。哪怕你已在 User 模型中正确启用了 use SoftDelete 并配置了 $deleteTime = 'delete_time',Db::name('user')->select() 仍会查出所有行——包括 delete_time 不为 NULL 的“已软删”记录。
- Db 不加载模型类,因此完全忽略
SoftDeletetrait、$deleteTime、withTrashed()等一切模型级逻辑 - 它生成的 SQL 就是
SELECT * FROM user,没有任何软删过滤 - 所谓“数据还在”,不是缓存或事务问题,而是 Db 本就不该过滤
想让 Db 查询也跳过软删数据?得手动加条件
如果你坚持用 Db(比如在复杂子查询、跨库操作或性能敏感场景),就必须自己补上软删判断:
- 显式排除:
Db::name('user')->where('delete_time', null)->select() - 注意字段类型匹配:若
delete_time是 DATETIME,用null;若是 INT 时间戳,用0或['neq', 0] - 别写
where('delete_time', 'IS NULL')—— ThinkPHP 不支持字符串形式的 SQL 片段,会报错
真正需要软删过滤时,请改用模型查询
软删除是模型层特性,不是数据库能力。只要涉及状态过滤、恢复、关联透传等,必须走模型:
- 查未删数据:
User::where('status', 1)->select() - 查全部(含已删):
User::withTrashed()->select() - 只查已删:
User::onlyTrashed()->select() - 恢复一条:
$user = User::onlyTrashed()->find(123); $user?->restore();
常见误解澄清
有人看到 Db 查出“已删数据”,就去清缓存、重启服务、检查事务——这些都没用。原因只有一个:
- Db 从不识别软删除,这不是 bug,是设计如此
- 用 Db 删除(
Db::name('user')->delete(1))是物理删除,哪怕模型启用了软删,也完全绕过 - 想统一行为,就不要混用 Db 和模型操作同一张表的生命周期管理











