thinkphp 5.0 中 delete() 后数据仍可查,说明软删除未生效:需确认模型启用 use softdelete 且 $usesoftdelete = true、数据库存在匹配类型的 delete_time 字段、查询显式调用 withouttrashed() 或配置全局作用域,否则默认不自动过滤。

ThinkPHP 5.0 中调用模型 delete() 后数据仍能查到,说明软删除未真正生效——这不是“删不掉”,而是软删除机制根本没被触发或被绕过。核心排查方向就三个:字段配置是否对、模型是否启用、查询是否默认过滤。
确认软删除字段已正确定义且数据库存在
软删除依赖一个真实存在的字段,且类型和值必须匹配框架预期:
- 检查模型中是否声明了 protected $deleteTime = 'delete_time';(字段名必须与数据库完全一致,区分大小写)
- 确认数据表中确实有该字段,类型推荐
DATETIME(可空)或BIGINT(时间戳),不能是VARCHAR或NOT NULL - 执行一次
$user->delete()后,直接查数据库,看delete_time是否被写入(如2026-10-03 12:15:00或时间戳),为空或为0表示未写入
检查模型是否真正启用了软删除行为
仅 use Trait 不够,TP5.0 需显式开启:
- 模型类中必须包含 use \think\model\concern\SoftDelete;
- 同时设置 protected $useSoftDelete = true;
- 若模型开启了自动时间戳(
$autoWriteTimestamp = true),需确保delete_time不在$createTime/$updateTime列表里,否则新增时就被误填
验证默认查询是否真的应用了软删除过滤
很多人误以为“开了软删除=自动屏蔽已删数据”,其实 TP5.0 默认并不自动过滤——它只在你显式使用 withoutTrashed() 或配置了全局作用域时才生效:
- 普通查询如
User::where('id', 1)->find()→ 不会加 delete_time IS NULL 条件,所以能查到已删数据 - 正确做法是在模型中定义作用域,例如:
public function scopeWithoutTrashed($query) { $query->whereNull('delete_time'); }
再在模型属性中加 protected $scope = ['withoutTrashed']; - 或者每次手动写:
User::withoutTrashed()->where(...)->find()
排除缓存和运行时干扰
有时不是逻辑问题,而是环境残留:
- 清空
runtime/cache/目录,避免模型结构或作用域被旧缓存锁定 - 如果用了 Redis 缓存,确认查询结果没被缓存住(比如
Cache::get('user_1')返回的是旧快照) - 临时关闭所有缓存测试:
config(['cache' => ['type' => 'null']]);
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











