在Laravel 9中恢复软删除记录的核心是先用withTrashed()或onlyTrashed()查出deleted_at非空的记录,再调用restore()清除该字段;默认查询自动过滤软删数据,故必须显式启用包含模式,否则find()等方法返回空。

在 Laravel 9 中恢复软删除记录,核心是先查出带 deleted_at 值的记录,再调用 restore() 方法。但要注意:默认查询会自动排除软删除数据,必须显式启用“包含已删除”模式才能查到它们,否则 find() 或 where() 直接返回空。
一、正确查出软删除记录
不能用常规方式查,必须使用以下任一方法获取已软删除的模型实例:
-
withTrashed():查所有记录(含已软删的),再加条件筛选,例如:User::withTrashed()->where('id', 123)->first(); -
onlyTrashed():只查已软删的记录,适合批量恢复,例如:User::onlyTrashed()->where('email', 'test@example.com')->first(); - 注意:直接
User::find(123)或User::where(...)->first()永远查不到软删除数据,因为 Eloquent 默认过滤掉了。
二、执行恢复操作
拿到模型实例后,调用 restore() 即可清除 deleted_at 字段:
- 单条恢复:
$user = User::withTrashed()->find(123);<br>if ($user && $user->trashed()) {<br> $user->restore();<br>} - 批量恢复(Laravel 9 原生支持):
User::onlyTrashed()->where('status', 'inactive')->restore();
这条语句会生成一条 SQL UPDATE,效率高,但不触发模型事件。
三、恢复后重置状态(关键补充)
Laravel 9 的 restore() 默认不触发 restored 事件,也不走模型生命周期(如 updating、updated),所以字段不会自动更新,缓存不会刷新,关联逻辑也不会执行。
- 若需重置字段(如把
status改回active,更新updated_at),得手动处理:$user->status = 'active';<br>$user->updated_at = now();<br>$user->saveQuietly(); // 避免二次触发事件
- 或封装一个安全的恢复方法:
public function restoreAndReset()<br>{<br> $this->restore();<br> $this->status = 'active';<br> $this->updated_at = now();<br> return $this->saveQuietly();<br>}
四、事务保障一致性(推荐用于关键业务)
如果恢复操作需联动写日志、更新统计、修改权限等,必须用数据库事务包裹,防止部分成功导致数据不一致:
use Illuminate\Support\Facades\DB;DB::transaction(function () use ($user) {<br> $user->restore();<br> AuditLog::create(['action' => 'restore', 'model_type' => User::class, 'model_id' => $user->id]);<br>});- 任一步失败,
deleted_at和日志都会回滚,确保原子性。


















