laravel 10/11中软删除通过deleted_at字段实现,需数据库迁移添加softdeletes()且模型使用softdeletes trait;查全部用withtrashed(),查仅软删用onlytrashed(),恢复用restore(),彻底删除用forcedelete()。

要在 Laravel 10 或 11 中查看和管理软删除数据,核心是理解 SoftDeletes trait 的行为机制——它不删数据,只设 deleted_at 时间戳;所有查询默认自动过滤掉已软删记录,必须显式调用作用域方法才能触达。
启用软删除的两个必要条件
缺一不可,否则 delete() 会变成硬删:
- 数据库表中存在
deleted_at字段(通过迁移添加:$table->softDeletes();) - 模型中正确引入 trait:
use Illuminate\Database\Eloquent\SoftDeletes;并在类中声明use SoftDeletes; - (可选但推荐)在模型中加
protected $dates = ['deleted_at'];,让框架自动转为 Carbon 实例,便于时间比较
查出软删除数据的三种方式
这些方法返回的是查询构造器,需接 get()、first()、count() 等终结方法才真正执行:
-
User::withTrashed()->get():查全部,含正常 + 已软删记录 -
User::onlyTrashed()->get():只查deleted_at IS NOT NULL的记录 -
User::withoutTrashed()->get():显式排除软删记录(等价于默认行为,一般不用写)
注意:这些作用域不影响关联预加载里的子查询。例如 User::withTrashed()->with('posts')->get(),posts 仍按 Post 模型自身的软删除配置过滤。
恢复与彻底删除操作
软删后数据仍在,可通过以下方式干预:
-
$user->restore():清空deleted_at,记录重新可见 -
User::onlyTrashed()->where('id', 5)->restore():链式恢复指定软删记录 -
$user->forceDelete():跳过软删逻辑,直接执行 SQLDELETE,不可逆 -
User::onlyTrashed()->where('created_at', 'subMonths(6))->forceDelete():批量清理过期软删数据
配合事件与业务场景的实用建议
软删除不是“设了就完事”,还需考虑实际维护成本:
- 监听
restoring/restored事件,用于同步更新关联状态或日志 - 定期跑命令清理长期无用的软删记录,避免表膨胀影响性能
- 在后台管理列表中,可用
onlyTrashed()单独展示“回收站”,提供一键恢复或强制删除入口 - 对外 API 接口默认不应返回软删数据;如需暴露,应明确加
include_trashed=1参数并做权限校验











