thinkphp中删除的数据能否恢复取决于删除方式:物理删除需依赖数据库备份或binlog,软删除则可通过restore()等方法恢复,但需正确配置deleted_at字段、启用softdelete、注意查询方法调用顺序及事务处理。

ThinkPHP 里删掉的数据能不能恢复,取决于你当初用的是物理删除还是软删除。如果是 delete() 直接执行的 DELETE SQL,那 PHP 层面基本没辙,得靠数据库备份或 binlog;但如果你提前启用了软删除,恢复就是几行代码的事——前提是配置对、调用对、字段类型也对。
软删除没生效,delete() 还是物理删
很多人加了 deleted_at 字段,模型里也写了 use SoftDelete;,结果一调 delete(),数据真没了。根本原因是:软删除不是默认开启的,必须显式声明字段和行为。
- 模型类里要写
use think\model\concern\SoftDelete;(注意不是带反斜杠的完整命名空间) - 必须定义
protected $deleteTime = 'deleted_at';,字段名要跟数据库一致 - 数据库字段类型必须是
DATETIME NULL或TIMESTAMP NULL,NOT NULL 会因约束失败导致静默跳过软删逻辑 - 如果字段叫
is_deleted或delete_time,就得对应改$deleteTime,不能依赖默认值
onlyTrashed() 和 withTrashed() 必须在 select() 前链式调用
这两个方法只影响当次查询,且顺序错一点就失效。比如 User::where('id', 123)->onlyTrashed()->find() 是错的——onlyTrashed() 被写在 where() 后面,框架根本不会识别。
- 正确写法:
User::onlyTrashed()->where('id', 123)->find()或User::onlyTrashed()->find(123) -
withTrashed()是查全部(含已软删),onlyTrashed()是只查已软删,别混淆用途 - 关联查询时不会自动继承,
User::withTrashed()->with('orders')中的orders仍是默认过滤状态,得单独写orders.withTrashed()
restore() 是实例方法,不能静态调用
User::where('id', 123)->restore() 会直接报错 Call to undefined method。因为 restore() 只挂在模型实例上,而且它不抛异常,失败只返回 false。
- 必须先查出软删记录:
$user = User::onlyTrashed()->find(123); - 再调实例方法:
if ($user) { $user->restore(); } - 检查返回值:
if (false === $user->restore()) { /* 字段被手动改过、权限不足或时间戳类型不匹配 */ } - 事务场景下,恢复后还有其他操作,记得自己
Db::startTrans()并控制回滚边界
批量恢复别硬套 restore(),优先用 update()
框架没有 restoreAll() 方法,所有“批量恢复”教程里出现的这个方法,都是开发者自己封装的。原生模型只支持单条 restore(),循环调用性能差、事务难控、还容易内存溢出。
- 最简方案:
Db::name('user')->where('id', 'in', [1,2,3])->update(['deleted_at' => null]); - 要触发模型事件(如
restored):用User::onlyTrashed()->whereIn('id', [1,2,3])->chunk(500, function ($items) { $items->each->restore(); }); - 字段是整型时间戳(
delete_time INT)时,别写null,得写0,并确保模型里有protected $type = ['delete_time' => 'integer'];
真正容易被忽略的点是字段类型和 NULL 约束——哪怕代码全对,只要数据库里 deleted_at 是 NOT NULL,或者存了 '0000-00-00 00:00:00' 这种非法值,restore() 就会静默失败,查不到数据时第一反应不该是“代码错了”,而是去数据库里 SELECT deleted_at FROM user WHERE id = 123; 看一眼实际值。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











