新闻中心 分类>>

Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】

2025-12-27 00:00:00
浏览次数:
返回列表
加了 SoftDeletes trait 还查不到 deleted_at 字段是因为该 trait 仅启用软删除逻辑,不自动添加数据库字段;必须手动创建迁移并使用 $table->softDeletes() 添加 deleted_at 字段。

为什么加了 SoftDeletes trait 还查不到 deleted_at 字段

因为 SoftDeletes 只是启用软删除逻辑,不会自动在数据库中添加 deleted_at 字段。必须手动迁移添加:

  • 运行 php artisan make:migration add_deleted_at_to_users_table
  • 在迁移文件的 up() 方法里写:
    public function up(Blueprint $table)
    {
        $table->softDeletes();
    }
  • 执行 php artisan migrate

注意:如果表已存在且有数据,softDeletes() 会添加可为 NULL 的 deleted_at 字段;但不会修改已有记录的该字段值,所以历史数据默认不被视为“已删除”。

调用 delete() 后数据没消失但 where 查询查不到

这是软删除的预期行为:调用 $user->delete() 会把 deleted_at 设为当前时间戳,而非真正删掉行。Laravel 默认的 Eloquent 查询会自动加上 WHERE deleted_at IS NULL 条件。

  • 想查出所有记录(含已软删除的):用 User::withTrashed()->get()
  • 只查已软删除的:用 User::onlyTrashed()->get()
  • 恢复单条:用 $user->restore()(会清空 deleted_at
  • 强制物理删除:用 $user->forceDelete()

注意:关联查询(如 $user->posts)默认也不会加载已软删除的关联记录,除非对应模型也用了 SoftDeletes 并显式调用 withTrashed()

restore() 不生效或报错 “Call to undefined method”

常见原因有两个:

  • 模型没 use Illuminate\Database\Eloquent\SoftDeletes trait,只加了迁移字段没用
  • 调用方式错误:比如对集合批量调用 restore() 时没用 each(),直接写 $users->restore() 会失败

正确批量恢复示例:

$users = User::onlyTrashed()->where('created_at', '<', now()->subWeek())->get();
$users->each->restore(); // 或 $users->each(function ($u) { $u->restore(); });

另外,如果模型启用了全局作用域(如多租户 scope),要确认 restore() 是否被拦截 —— 它不触发 creating/updating 等事件,但会触发 restoringrestored 事件。

软删除后关联数据怎么处理:级联 or 保留

Laravel 不自动处理软删除的关联级联。比如 User 软删除,它的 Post 记录默认仍可查(除非 Post 自己也用了 SoftDeletes)。

  • 想让关联也软删除:需手动在模型事件里实现,例如监听 deleting 事件,然后调用 $this->posts()->update(['deleted_at' => now()])
  • 想物理删除关联:监听 forceDeleted 事件,再执行 $this->posts()->forceDelete()
  • 避免误恢复时带出脏关联:恢复主模型前,先检查并同步恢复关联模型(需自行编码逻辑)

没有银弹方案。是否级联、怎么级联,得看业务——回收站功能通常要求“主模型恢复时,其软删除的子数据也一并恢复”,这必须自己控制,Eloquent 不代劳。

搜索