restore()静默失败的三个常见原因是:数据库delete_time字段非null类型导致写入null被拒;模型未启用softdelete(低版本需显式设置$usesoftdelete=true);$deletetime字段名在主模型与关联模型中不一致。

restore() 静默失败的三个常见原因
调用 $user->restore() 返回 false 却不报错,是软删除恢复中最容易卡住的地方。它不抛异常,只默默跳过,结果数据库里 delete_time 还是非空。
- 数据库字段不是
NULL类型:比如定义成DATETIME NOT NULL DEFAULT '1970-01-01',框架尝试写入NULL时被 MySQL 拒绝,但 PHP 层不捕获这个 SQL 错误 - 模型没真正启用
SoftDelete:只写了use SoftDelete;但漏了protected $useSoftDelete = true;(TP6.0+ 可省略,但低版本必须显式设) -
$deleteTime字段名不一致:主模型写的是'delete_time',关联模型却用了'deleted_at'且没声明protected $deleteTime = 'deleted_at';,导致关联调用restore()直接忽略
批量恢复必须避开 onlyTrashed()->where()->restore() 这个坑
很多人写 UserModel::onlyTrashed()->where('status', 1)->restore(),以为能批量恢复,实际无效——restore() 不接受链式条件后的结果集,它只对当前实例生效,而 onlyTrashed()->where() 返回的是查询构造器,不是模型集合。
- 安全做法是先取 ID 列表:
$ids = UserModel::onlyTrashed()->where('status', 1)->column('id');,再用update()直写:UserModel::whereIn('id', $ids)->update(['delete_time' => null]); - 若需触发
restored事件,改用chunk()分页查出模型实例:UserModel::onlyTrashed()->where('status', 1)->chunk(200, function ($users) { $users->each->restore(); });,注意闭包内要判断每条restore()返回值 - 别在事务外执行批量恢复:某条失败会导致部分数据已恢复、部分仍软删,状态撕裂
关联模型不会自动恢复,必须手动逐层处理
$user->restore() 只清 user 表的 delete_time,订单、地址、日志等关联表哪怕也启用了 SoftDelete,也不会被连带恢复。
- 不能依赖
with(['orders'])或$user->orders—— 它们默认过滤掉软删记录,查不到任何数据 - 正确路径是:先查出该用户的软删订单:
$user->orders()->onlyTrashed()->select(),再遍历调用$order->restore() - 量大时建议用
Db::name('order')->where('user_id', $user->id)->whereNotNull('delete_time')->update(['delete_time' => null]),但会跳过事件和验证逻辑 - 若在模型
restored事件里自动拉取关联恢复,务必加防循环标记,比如if ($this->getAttribute('skip_restore_relations')) return;
force()->delete() 和 destroy(, true) 的区别与风险
彻底物理删除软删数据,必须走模型层的强制删除路径,否则直接 SQL 删除会绕过所有钩子和清理逻辑。
-
$user->force()->delete()是实例方法,会触发deleting/deleted事件,适合单条操作 -
UserModel::destroy($id, true)是静态方法,第二个参数true表示 force,但要注意:它不支持传数组批量 + force,UserModel::destroy([1,2,3], true)在 TP6 中实际仍走软删 - 真要批量硬删,得用
UserModel::onlyTrashed()->whereIn('id', $ids)->delete()—— 此时delete()因前置onlyTrashed()已处于“可硬删上下文”,但依然推荐显式加force()更清晰 - 切记:一旦物理删除,
restore()就永远失效了,没有后悔键
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











