跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

ThinkPHP事件怎么做数据恢复_ThinkPHP恢复指南【解答】

ThinkPHP 的 restore() 触发 restoring(恢复前,返回 false 可中断)和 restored(恢复后,仅当 delete_time 确实置为 NULL 时触发);需在模型中配置事件或绑定监听器;restoring 中可校验权限或业务规则并返回 false 阻止非法恢复;restored 中宜用 saveAll 批量恢复关联数据;所有操作应包裹在 Db::transaction 中确保事务一致性。 ThinkPHP 本身没有“事件驱动的 数据恢复 ”机制,所谓“事件做数据恢复”,其实是把模型事件(如
restoring
、
restored
)和软删除恢复逻辑配合使用,用来在恢复前后插入校验、日志、关联处理等动作——它不替代恢复本身,只是增强恢复过程的可控性。 restore() 触发哪些模型事件 调用
$model->restore()
时,ThinkPHP 会按顺序触发:
restoring
:恢复前触发,可在此中断恢复(返回
false
)
restored
:恢复成功后触发,仅当数据库字段真实更新为
NULL
才触发 注意:
restoring
和
restored
是模型实例事件,不是静态方法或全局钩子;必须在模型类中定义
protected $event = [...]
或使用
observe()
绑定监听器。 怎么在 restoring 中阻止非法恢复 比如只允许管理员恢复、或禁止恢复已过期的记录,可在
restoring
回调里加判断: 立即学习 “ PHP免费学习笔记(深入) ”;
public function restoring() { if (!auth('admin')->check()) { return false; // 中断恢复 } if ($this->delete_time && strtotime($this->delete_time) < time() - 86400 * 30) { Log::warning('attempt_restore_expired', ['id' => $this->id]); return false; } }
关键点: PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 返回
false
会直接终止本次
restore()
,且不报错,只静默失败
$this->delete_time
是原始字段值,不是 PHP 时间戳,需手动转换 事件里不能用
throw new Exception()
,否则整个事务会崩,且
restore()
返回
false
而非异常 restored 事件里怎么安全处理关联数据 软删除默认不级联,但你可以在
restored
里主动拉取并恢复关联项:
public function restored() { // 恢复订单下的所有订单项 $this->items()->onlyTrashed()->chunk(100, function ($items) { foreach ($items as $item) { $item->delete_time = null; } OrderItem::saveAll($items); }); }
注意: 别在
restored
里调
$this->items()->restore()
—— 关联模型没启用
SoftDelete
trait 的话会报错 用
saveAll()
批量更新比循环调
restore()
更高效,也避免触发重复事件 如果关联模型也有
restored
事件,它们会各自触发,无需额外注册 事件 + 事务恢复时最容易漏掉的一件事 模型事件默认不在事务内自动回滚。比如你在
restored
里写了一条日志到另一张表,但主恢复因数据库约束失败了,那条日志仍会留在库里。 正确做法是:手动开启事务,并确保事件里的所有操作都共享同一连接:
Db::transaction(function () use ($user) { if (false === $user->restore()) { throw new Exception('Restore failed'); } // 日志、关联更新等都在同一事务里 });
否则,哪怕
restore()
成功,后续事件里的 DB 操作失败,也不会回滚主记录的恢复状态——这是线上恢复出错后数据不一致的常见根源。

相关文章