Laravel 软删除通过标记 deleted_at 字段实现数据逻辑删除,需添加字段、引入 SoftDeletes trait 并设置 $dates 属性,delete() 方法自动填充 deleted_at,查询默认忽略已删除数据,withTrashed() 包含已删记录,onlyTrashed() 仅查已删数据,restore() 恢复,forceDelete() 永久删除,支持 restoring、restored 等事件监听,适用于需保留历史的数据场景。

在 Laravel 中,软删除(Soft Deleting)是一种让数据“看似”被删除,实则保留在数据库中的机制。它通过标记一条记录为已删除,而不是真正从数据库中移除,从而保留数据完整性,便于后续恢复或审计。Laravel 的 Eloquent ORM 提供了非常简洁的方式来实现软删除功能。
启用软删除功能
要在模型中启用软删除,需完成以下三个步骤:
- 在对应的数据表中添加 deleted_at 字段
- 在模型类中引入 Illuminate\Database\Eloquent\SoftDeletes trait
- 将 deleted_at 添加到模型的 $dates 属性中(可选,但推荐)
1. 修改数据库迁移文件
在创建表或修改表结构时,使用 softDeletes() 方法添加 deleted_at 字段:
Schema::table('users', function (Blueprint $table) {
$table->softDeletes();
});
这会创建一个可为空的 deleted_at 时间戳字段。
2. 在模型中使用 SoftDeletes Trait
打开对应的 Eloquent 模型(如 User.php),引入 SoftDeletes:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
}
加入 $dates 后,deleted_at 会被自动转换为 PHP 的 Carbon 实例,方便日期操作。
软删除的使用方法
启用后,调用模型的 delete() 方法不会真正删除记录,而是填充 deleted_at 字段为当前时间。
- $user->delete():触发软删除,设置 deleted_at
- User::find($id):默认不返回已被软删除的记录
- User::withTrashed()->find($id):包含已删除的记录
- User::onlyTrashed()->get():仅查询已被软删除的记录
- $user->restore():恢复已软删除的记录(清空 deleted_at)
- $user->forceDelete():强制永久删除,绕过软删除
示例:
$user = User::find(1); $user->delete(); // 软删除 // 查询包含已删除用户 User::withTrashed()->find(1); // 恢复用户 $user->restore(); // 永久删除 $user->forceDelete();
查询作用域说明
Laravel 默认会在所有查询中自动添加 WHERE deleted_at IS NULL 条件,这就是为什么普通 find() 或 get() 看不到已删除数据的原因。
你可以根据需要切换查询范围:
- withoutTrashed():等同于默认行为,排除已删除数据
- withTrashed():包含所有数据,无论是否删除
- onlyTrashed():只获取已软删除的数据
恢复事件与清理
软删除和恢复操作会触发相应的 Eloquent 事件:
- deleting 和 deleted:delete() 时触发(软或硬)
- restoring 和 restored:restore() 时触发
你可以在模型中监听这些事件,执行额外逻辑:
protected static function booted()
{
static::restored(function ($user) {
// 用户被恢复时执行
Log::info('User restored: ' . $user->id);
});
}
基本上就这些。只要记得加字段、用 Trait、理解查询作用域,软删除用起来非常自然。日常开发中适合用于用户、文章、订单等需要保留历史记录的场景。










