Laravel如何软删除数据_Laravel软删除实现原理【详解】

蓮花仙者

蓮花仙者

2026-05-01

760人浏览

原创

软删除需同时满足模型引入softdeletes trait且数据库表存在可为空的deleted_at字段;否则delete()将执行物理删除或报错。

laravel如何软删除数据_laravel软删除实现原理【详解】

软删除在 Laravel 中不是默认行为,必须同时满足两个硬性条件:模型引入 SoftDeletes trait 且数据库表存在可为空的 deleted_at 字段;缺一不可,否则 delete() 会直接执行物理删除或报错。

为什么 delete() 还是真删了?检查 trait 和字段是否都到位

最常见的误判是以为加了 trait 就够了,或者只改了迁移但没跑命令。软删除完全失效时,大概率是以下任一情况:

  • deleted_at 字段缺失、类型非 TIMESTAMP NULL(MySQL)或 DATETIME NULL(PostgreSQL/SQLite)
  • 模型里漏写了 use SoftDeletes;,或 use 语句写在了 class 声明之后
  • 字段名被手动改成 is_deleteddeleted_time 等,而没重写 getDeletedAtColumn() 方法
  • 迁移中用了 $table->softDeletes()->nullable() —— softDeletes() 本身已隐含 nullable(),重复调用可能触发异常

withTrashed() 和 onlyTrashed() 怎么用才不踩坑

这两个方法本质是动态移除或替换全局作用域,不是“开关”式配置。它们只影响当前查询链,且不能混用:

Laravel 13.2.0
Laravel 13.2.0

PHP中文网提供Laravel 13.2.0版本下载,Laravel框架 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。

下载
  • User::withTrashed()->where('name', 'John')->get() → 返回所有匹配记录,含已软删的
  • User::onlyTrashed()->where('name', 'John')->get() → 只返回 deleted_at IS NOT NULL 且 name 匹配的记录
  • User::withTrashed()->onlyTrashed() 无效,后者会覆盖前者,等价于只调 onlyTrashed()
  • 关联查询(如 $user->posts)默认也受父模型软删状态影响;若要查出用户已软删但文章仍可见,需单独对关系调用 withTrashed()$user->posts()->withTrashed()->get()

restore() 不生效?先确认它是不是真被软删过

restore() 只对 deleted_at IS NOT NULL 的记录有效,且不会触发事件(除非显式配置 $dispatchesEvents)。常见失效场景:

  • 之前执行过 forceDelete() 或原生 SQL DELETE,数据已彻底消失,restore() 无从恢复
  • 调用 $user->restore() 后查不到,是因为默认查询仍过滤掉软删记录;得用 User::withTrashed()->find($id) 先拿到实例再恢复
  • 批量恢复必须带 withTrashed():正确写法是 User::withTrashed()->where('deleted_at', '!=', null)->restore();直接 User::where(...)->restore() 查不到目标,结果为空
  • restore() 不会级联更新关联模型的 deleted_at,父子软删需自行处理逻辑(比如监听 restored 事件后手动恢复子记录)

性能与兼容性容易被忽略的点

软删除看似轻量,但在高并发或大数据量场景下,几个细节直接影响稳定性和效率:

  • deleted_at 字段必须加索引,尤其当表行数超 10 万后,onlyTrashed() 查询会明显变慢;迁移中补加:$table->index('deleted_at');
  • 字段设为 NOT NULL 或带 DEFAULT CURRENT_TIMESTAMP 会导致 delete() 报 SQL 错误——trait 尝试写入 NULL,但数据库拒绝
  • Laravel 6+ 已自动识别 deleted_at 为日期类型,$dates = ['deleted_at'] 非必需,但保留它可确保 Carbon 实例化,避免时间比较出错
  • 唯一索引字段(如 email)在软删后仍占用约束,新用户注册同邮箱会失败;解决方案是改用组合索引:UNIQUE(email, deleted_at),让已删记录的 deleted_at 非空,从而绕过冲突

相关专题

更多
laravel组件介绍
laravel组件介绍

laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

2024.04.09

672

10

laravel中间件介绍
laravel中间件介绍

laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

2024.04.09

648

9

laravel使用的设计模式有哪些
laravel使用的设计模式有哪些

laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

2024.04.09

1112

10

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.10

1568

7

laravel入门教程
laravel入门教程

本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

2025.08.05

1920

22

laravel实战教程
laravel实战教程

本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

2025.08.05

1245

13

laravel面试题
laravel面试题

本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.05

2739

7

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

2026.03.04

1087

29

Laravel 框架安装指南
Laravel 框架安装指南

本指南详解 Laravel 框架安装全流程,涵盖 PHP 8.1+ 环境配置、Composer 依赖管理工具安装及国内镜像源优化。重点演示使用 composer create-project 命令创建 Laravel 10/11 项目,解决常见安装错误与依赖冲突。从环境搭建到项目初始化,助您快速完成 Laravel 开发环境部署,为后续 Web 应用开发奠定基础。适合 PHP 初学者与框架迁移开发者参考。

2026.04.09

91

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何安装 Composer
如何安装 Composer

共1课时 | 128人学习

Composer手册
Composer手册

共0课时 | 0人学习