thinkphp软删除默认不自动过滤已删记录,需显式调用withouttrashed()或配置全局作用域;字段名、类型须与模型定义严格一致,否则查询失效或报错。

ThinkPHP 软删除字段没生效,查出来还是被删的记录
默认情况下,ThinkPHP 的软删除模型(继承 SoftDelete)**不会自动过滤已软删除的数据**,除非你显式调用 withTrashed() 或 onlyTrashed() —— 但反过来说,不加任何修饰的查询,默认就是「包含软删除数据」的。这是最常踩的坑:以为开了软删除就自动屏蔽,结果列表里冒出一堆“已删除”的脏数据。
原因在于 ThinkPHP 的设计逻辑:软删除只是给模型加了个查询作用域(scope),不是全局拦截器。它只在你主动使用 select()、find() 等方法时,才根据当前是否启用软删除作用域来拼 WHERE 条件。
- 普通查询如
UserModel::where('status', 1)->select()→ 不触发软删除过滤 - 正确写法是
UserModel::withoutTrashed()->where('status', 1)->select() - 或者更推荐:在模型初始化时统一绑定作用域,比如在
initialize()里写$this->useSoftDelete('delete_time', 0);,再配合全局作用域
如何让所有查询默认排除软删除数据
想省去每次手写 withoutTrashed()?得靠全局作用域 + 模型配置。ThinkPHP 6.0+ 支持在模型类中定义 protected $scope = ['withoutTrashed'];,但这只是声明,真正起效还得靠作用域方法本身返回闭包。
- 在模型中定义
public function scopeWithoutTrashed($query),内部调用$query->whereNull('delete_time')(假设软删字段是delete_time) - 确保模型启用了软删除:
use SoftDelete;并设置了protected $deleteTime = 'delete_time'; - 注意字段类型:如果
delete_time是int类型(时间戳),就得用$query->where('delete_time', 0),不能用whereNull - 别在控制器里反复写作用域——作用域一旦注册,
select()、paginate()、count()都会自动带上
withTrashed() 和 onlyTrashed() 的实际用途
这两个方法不是“可有可无的装饰”,而是明确区分管理场景的关键开关。比如后台用户列表要显示全部(含已删),但前端 API 必须严格隔离;又比如回收站页面只展示已删数据。
-
withTrashed():取消软删除过滤,查出所有记录(含delete_time != null的) -
onlyTrashed():只查delete_time IS NOT NULL的记录,等价于whereNotNull('delete_time') - 它们会覆盖模型默认作用域,所以即使你设了全局
withoutTrashed,调用withTrashed()后也会失效 - 注意:调用
withTrashed()后,delete_time字段值仍是原始值,不会被自动转成可读格式,需要自己用date()或模型访问器处理
软删除字段名或类型配错导致查询异常
最常见的报错是 SQLSTATE[42S22]: Column not found: 1054 Unknown column 'delete_time' in 'where clause',或者查出来数据全为空——基本都是字段名/类型没对上。
- 确认数据库表里真实存在的软删除字段名,比如有的叫
is_deleted(tinyint)、有的叫deleted_at(datetime),必须和模型中$deleteTime值完全一致 - 字段类型决定判断方式:
datetime或timestamp用whereNull();int或tinyint用where('field', 0) - 如果用的是自定义软删除字段(非
delete_time),记得在模型里显式指定:protected $deleteTime = 'is_deleted'; protected $defaultSoftDelete = 0; - 迁移文件里漏加字段、字段名拼错、甚至大小写不一致(尤其 MySQL 在某些配置下区分大小写),都会让软删除逻辑静默失效
软删除不是开个开关就完事,它依赖字段存在性、类型一致性、作用域注册时机三个硬条件。少一个,查询就可能漏过滤或直接报错。特别是多模型共用一套迁移脚本时,最容易在某个模型里忘改 $deleteTime。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











