
软删字段没设对,restore() 会静默失败
ThinkPHP 的软删依赖模型里 delete_time 字段(默认名),但很多人直接用 softDelete() 没配字段,或数据库里字段类型是 VARCHAR、INT 却没设成 NULL 允许值。结果调 restore() 时没报错,数据却始终查不到——因为底层 SQL 是 WHERE delete_time IS NULL,而你的字段存的是 ‘0’ 或 0,根本匹配不上。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
确认模型中已显式声明软删字段:protected $softDelete = [‘field’ => ‘delete_time’, ‘format’ => ‘datetime’];数据库字段必须是 DATETIME 或 TIMESTAMP 类型,且允许 NULL如果历史数据里 delete_time 存的是 0 或 ‘0000-00-00 00:00:00’,先用 SQL 批量转成 NULL:UPDATE table_name SET delete_time = NULL WHERE delete_time = ‘0000-00-00 00:00:00’;
批量恢复要绕开 restore() 的单条限制
restore() 默认只作用于当前模型实例,传 ID 数组进去不会生效;想批量恢复,得手动拼条件 + saveAll() 或原生查询。否则容易写成循环调 restore(),N 条 SQL,性能崩,事务也难控。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
用 Db::name(‘table’)->where(‘id’, ‘in’, [1,2,3])->update([‘delete_time’ => null]); 最直接如果必须走模型逻辑(比如要触发事件),先查出对象集合再批量更新:$models = User::onlyTrashed()->whereIn(‘id’, [1,2,3])->select(); foreach ($models as $m) { $m->delete_time = null; } User::saveAll($models);注意:模型的 saveAll() 不会自动跳过软删状态,所以必须显式赋值 delete_time => null,不能只调 restore()
误删后查不到数据?先确认是否真在回收站里
ThinkPHP 的“软删”不是把数据挪到另一张表,而是靠 delete_time 标记。所以 select() 默认不查已软删记录,onlyTrashed() 才能捞出来。很多人执行了 delete(),回头用 find() 查不到,就以为数据丢了,其实只是没切到回收站视图。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
查软删数据必须加 onlyTrashed():User::onlyTrashed()->where(‘id’, 123)->find();恢复前建议先验证存在性:User::onlyTrashed()->where(‘id’, 123)->value(‘id’) 返回非 null 才继续别依赖 withTrashed() 做恢复操作——它只是查的时候包含软删记录,restore() 仍需单独调用
事务里恢复软删数据,记得检查 delete_time 是否被自动填充
有些模型开启了自动时间戳(createTime/updateTime),而 delete_time 又被 TP 自动识别为软删字段。在事务中调 restore() 后再 save(),可能触发 updateTime 更新,甚至意外重写 delete_time ——尤其当 softDelete 配置里 format 和模型时间格式不一致时。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
恢复操作尽量原子化:直接 update 字段,避免走完整 save() 流程若必须用模型,临时关闭时间自动写入:User::disableTimestamps(); 再操作测试时用 getLastSql() 看生成的 SQL,确认没有多余的 delete_time = NOW() 或 update_time = …事情说清了就结束。软删恢复看着简单,真正卡住人的永远是字段定义和 SQL 执行路径的细微偏差。

评论(0)