thinkphp软删除不生效的核心原因是模型配置、数据库字段、调用方式三者未对齐;需同时满足正确引入softdelete trait、显式配置$deletetime和$usesoftdelete(6.0.0–6.0.7)、delete_time字段为datetime/timestamp且nullable default null、必须通过模型方法(非db类)调用,并注意withtrashed()位置及关联查询的软删继承。

ThinkPHP模型软删除不生效,核心是模型配置、数据库字段、调用方式三者未对齐。漏掉任一环节,delete()就会变真删,restore()也静默失败。
模型是否真正启用 SoftDelete
只写 use SoftDelete; 不够,必须同时满足:
- 导入正确命名空间:
use think\model\concern\SoftDelete; - 类内声明 trait:
use SoftDelete; - 显式指定软删字段:
protected $deleteTime = 'delete_time';(即使用默认名也建议写上) - ThinkPHP 6.0.0–6.0.7 版本必须加开关:
protected $useSoftDelete = true; - 改完后运行
php think optimize:schema刷新模型缓存,否则旧配置仍生效
delete_time 字段定义是否合规
数据库字段是硬性门槛,错一点就全链路失效:
- 字段类型必须是
DATETIME或TIMESTAMP -
Null列必须为YES(即允许 NULL) -
Default值必须为NULL,不能是'1970-01-01'或CURRENT_TIMESTAMP - 执行
DESCRIBE user;验证;若不合规,用以下语句修复:ALTER TABLE `user` MODIFY COLUMN `delete_time` DATETIME NULL DEFAULT NULL;
操作是否走模型层而非 Db 直连
软删除是模型拦截机制,绕过模型等于绕过软删:
- ✅ 正确调用:
UserModel::destroy(123)、$user->delete()、UserModel::destroy([1,2,3]) - ❌ 错误调用:
Db::name('user')->delete(123)、UserModel::where('id', 123)->delete()——这些直连 Db,直接物理删除 - 查软删数据需显式调用:
UserModel::onlyTrashed()->select()或UserModel::withTrashed()->select()
全局作用域或关联查询是否干扰软删逻辑
withTrashed() 不是万能开关,容易被其他逻辑覆盖:
- 检查模型是否重写了
baseScope()方法,删掉或绕过其中对delete_time的硬性限制 -
withTrashed()必须放在链式调用最前端,如UserModel::withTrashed()->where('status', 1)->paginate(10);写成where()->withTrashed()会失效 - 关联查询(如
with('posts'))不会自动继承主模型的软删状态;要在关联方法里加->withTrashed(),或用闭包:with(['posts' => function($q) { $q->withTrashed(); }])
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











