tp6软删除失效因模型、字段、调用未对齐。需正确引入softdelete trait、配置$deletetime、启用$usesoftdelete(旧版)、确保delete_time字段为datetime/timestamp且nullable,默认null,并通过模型层调用delete()/restore()。

TP6 接口软删除失效,不是框架坏了,而是模型、字段、调用三者没对齐。只要漏掉一个环节,delete() 就会变成真删,restore() 也静默失败,前端查不到“已删数据”,后端还原不了——问题往往出在配置细节上。
检查模型是否真正启用 SoftDelete
只写 use SoftDelete; 不够,必须同时满足:
- 导入正确命名空间:
use think\model\concern\SoftDelete; - 类内声明 trait:
use SoftDelete; - 显式指定字段名:
protected $deleteTime = 'delete_time';(即使用默认名也建议写上) - 低版本(TP6.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;
确保删除和查询走的是模型层
软删除是模型拦截机制,绕过模型就等于绕过软删:
- ✅ 正确调用:
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()
接口中恢复与状态返回要显式处理
前端需要明确知道某条数据是否被软删,不能靠猜:
- 列表接口返回时,主动带上
is_deleted字段:$users = UserModel::field('id,name,delete_time')->select();<br>foreach ($users as &$u) { $u['is_deleted'] = !is_null($u['delete_time']); } - 点击“还原”时,必须先查出模型实例再调用
restore():$user = UserModel::onlyTrashed()->find($id);<br>if ($user && $user->restore()) { /* 成功 */ } else { /* 失败,检查返回值 */ } - 永久删除需显式加
force(true):UserModel::where('id', $id)->force(true)->delete();











