软删除数据可恢复,前提是模型启用SoftDeletes且deleted_at字段存在且非NULL;需通过实例调用restore(),避免直改数据库字段。

软删除的数据能恢复,但必须满足两个前提:模型启用了软删除,且数据库记录未被真正清除(deleted_at 字段非 NULL 但行还在)。
确认模型是否启用软删除
检查模型类是否 use SoftDeletes trait,并声明了 $dates 或(Laravel 9+)使用 $casts 自动处理 deleted_at:
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
// Laravel 8 及以下可能还需:
// protected $dates = ['deleted_at'];
// Laravel 9+ 推荐用:
// protected $casts = ['deleted_at' => 'datetime'];
}
没加 SoftDeletes trait 的模型调用 restore() 会报错:Call to undefined method restore();加了但没迁移字段,deleted_at 列不存在,操作会静默失败或抛出 SQL 错误。
- 运行
php artisan make:migration add_deleted_at_to_posts_table补字段(类型为timestamp,允许 NULL) - 执行
php artisan migrate - 已有数据的表,补字段后无需手动填 NULL —— Eloquent 软删除逻辑依赖该字段为 NULL 表示“未删除”
restore() 方法只能恢复单条已软删除记录
restore() 是实例方法,不是静态/查询构造器方法。直接写 Post::restore() 会报错:Call to undefined method restore()。
- 正确做法是先查出目标记录(带
withTrashed()),再调用实例restore():
$post = Post::withTrashed()->find(123);
if ($post && $post->trashed()) {
$post->restore(); // 成功返回 true
}
- 批量恢复?不能直接链式调用
restore(),但可用where('deleted_at', '!=', null)->update(['deleted_at' => null]),不过这绕过了模型事件(如restoring、restored)和访问器逻辑 - 更安全的批量恢复方式是先取 ID 列表,再逐个
restore(),或用集合的each():
Post::withTrashed()
->where('deleted_at', '!=', null)
->where('created_at', '>', '2024-01-01')
->get()
->each->restore();
restore() 不触发 saving/saved,但会触发 restoring/restored
这是关键行为差异:软删除恢复不是“新建”或“更新”,而是状态回切,因此跳过常规的模型保存生命周期钩子。
- 如果你在
saving中做了强制字段校验,它不会运行;但restoring和restored会触发,可用于审计、日志或关联修复 - 例如,恢复文章时自动重置评论计数(如果之前软删除时降为 0):
protected static function booted()
{
static::restoring(function ($post) {
// 恢复前可做权限检查、状态预处理
});
static::restored(function ($post) {
$post->comments_count = $post->comments()->count();
$post->saveQuietly(); // 避免再次触发事件循环
});
}
-
saveQuietly()在 Laravel 9.25+ 才有;旧版本请用save(['touch' => false])或临时移除监听器
deleted_at 字段被手动清空会导致 restore() 失效
有人为“快速恢复”直接执行 SQL:UPDATE posts SET deleted_at = NULL WHERE id = 123,这会让记录看起来像“从未删除”,但 Eloquent 内部状态不一致 —— $model->trashed() 仍可能返回 true(因缓存或属性未刷新),后续调用 restore() 会无效果甚至报错。
- 永远通过 Eloquent 的
restore()或forceDelete()操作软删除状态,不要直改deleted_at - 若已误操作,需 reload 模型:
$post->refresh(),再判断状态 - 生产环境建议加 DB 日志或审计中间件,监控对
deleted_at的直接 UPDATE
真正容易被忽略的是:软删除恢复不是“撤销删除操作”,而是“将删除标记取消”。只要 deleted_at 还在表里、值非 NULL,就始终可逆;一旦执行了 forceDelete() 或手工 DELETE FROM,Eloquent 就彻底无能为力了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











