0

0

Laravel软删除?数据软删除如何使用?

小老鼠

小老鼠

发布时间:2025-09-12 08:48:01

|

1021人浏览过

|

来源于php中文网

原创

Laravel软删除通过标记deleted_at字段实现逻辑删除,保留数据以便恢复和审计。在模型中使用SoftDeletes trait,并添加deleted_at字段,调用delete()时仅更新该字段而非物理删除。可使用withTrashed()、onlyTrashed()查询软删除数据,restore()恢复数据,forceDelete()彻底删除。需注意唯一约束冲突、索引性能及存储增长问题,合理设计可兼顾数据安全与系统效率。

laravel软删除?数据软删除如何使用?

Laravel的软删除机制,简单来说,就是一种“假删除”:数据在数据库中依然存在,但通过标记(通常是一个

deleted_at
时间戳字段)来指示它已被逻辑删除,不再出现在常规查询结果中。这极大地提升了数据恢复的可能性,也为数据审计和历史追溯提供了便利。

在Laravel中实现软删除,首先需要在你的模型上使用

Illuminate\Database\Eloquent\SoftDeletes
Trait。接着,在对应的数据库表中添加一个
deleted_at
字段,通常是一个
timestamp
类型,并且允许为
NULL
。当调用模型的
delete()
方法时,Eloquent不会真正从数据库中移除这条记录,而是将
deleted_at
字段设置为当前时间。

为什么选择Laravel软删除而非物理删除?

我个人觉得,在大多数业务场景下,软删除几乎是首选。你想想看,谁没手滑过?或者说,业务需求总是变来变去,今天说要彻底删除的数据,明天可能又因为某个报告或者审计要求,需要追溯回来。物理删除,那可就是覆水难收了。

我曾经在项目里遇到过一个情况,用户投诉说他提交的某个订单不见了。如果当时我们采取的是物理删除,那这个订单信息就真的找不回来了,后续的调查和处理都会变得非常麻烦。但因为我们用了软删除,只需要在后台把这个订单“恢复”一下,或者至少能看到它的历史记录,很快就能定位问题,甚至能直接恢复数据,这极大地降低了运营风险和客户服务成本。

除了数据恢复,软删除还有几个显而易见的优势:

  • 数据审计与追溯: 很多行业都有合规性要求,需要保留一定时期内的数据操作记录。软删除能让你轻松地查看哪些数据被“删除”过,什么时候“删除”的。
  • 保持数据完整性: 想象一下,如果你的用户表和订单表之间有外键关联。物理删除一个用户,可能会导致其所有订单也一并被删除(如果设置了级联删除),或者因为外键约束而删除失败。软删除则避免了这种连锁反应,你可以让用户“消失”,但他的历史订单数据依然完整地保留着,方便日后分析。
  • 避免ID冲突: 有些系统对ID的唯一性有严格要求。如果物理删除了一个记录,然后又创建了一个新记录,新的记录可能会获得之前被删除记录的ID,这在某些情况下可能会引发逻辑混乱。软删除则完全规避了这个问题。

当然,软删除也不是万能药。对于那些确实需要彻底销毁,不能留下任何痕迹的敏感数据(比如符合GDPR等隐私法规要求的数据),物理删除才是更合适的选择。但这种场景通常需要更严谨的数据生命周期管理策略来配合。

在Laravel中实现软删除的具体步骤与常见陷阱

实现软删除的步骤其实非常直接,但有些小细节不注意,可能会踩坑。

第一步:添加

deleted_at
字段到数据库表

你需要为你的模型对应的数据库表添加一个

deleted_at
字段。通常通过迁移文件来完成:

Schema::table('your_table_name', function (Blueprint $table) {
    $table->softDeletes(); // 这会添加一个可空的 timestamp 字段
});

如果你想移除软删除功能,也可以在迁移中这样做:

Schema::table('your_table_name', function (Blueprint $table) {
    $table->dropSoftDeletes();
});

第二步:在Eloquent模型中使用

SoftDeletes
Trait

在你的模型文件中,引入并使用

SoftDeletes
Trait:

第三步:执行“删除”操作

现在,当你调用模型的

delete()
方法时,它会执行软删除:

$post = App\Models\Post::find(1);
$post->delete(); // 这会将 post_id 为 1 的记录的 deleted_at 字段设置为当前时间

常见陷阱:

  1. 唯一约束问题: 这是一个经典问题。假设你有一个
    users
    表,
    email
    字段是唯一的。如果一个用户被软删除了,他的
    email
    还在数据库里。这时,如果另一个新用户尝试注册并使用相同的
    email
    ,数据库的唯一约束就会报错。
    • 解决方案: 你可以在数据库层面调整唯一约束,使其忽略
      deleted_at
      NULL
      的记录。例如,在MySQL中,你可以创建一个复合唯一索引,将
      email
      deleted_at
      (或者
      deleted_at
      NULL
      时的一个固定值)组合起来。或者,在应用层面,在创建新用户前,先检查软删除的用户中是否存在相同email,并提供恢复或强制删除的选项。
  2. 查询性能: 对于非常大的表,如果
    deleted_at
    字段没有索引,每次查询时都需要扫描整个表来排除软删除的记录,这可能会影响性能。
    • 解决方案: 确保为
      deleted_at
      字段添加索引。Laravel的
      softDeletes()
      方法在创建字段时通常会自动添加索引,但最好还是检查一下。
  3. 外键约束: 如果你的模型与其他模型存在外键关联,并且你希望在软删除时保持这种关联,那软删除就非常方便。但如果你期望级联删除(即删除主记录时,相关联的子记录也一并删除),那么软删除就不会触发数据库层面的级联删除。你需要手动在应用逻辑中处理这种级联软删除。

软删除数据如何查询、恢复与彻底移除?

一旦数据被软删除,常规的Eloquent查询是不会返回这些记录的。你需要一些特殊的方法来操作它们。

传媒公司模板(RTCMS)1.0
传媒公司模板(RTCMS)1.0

传媒企业网站系统使用热腾CMS(RTCMS),根据网站板块定制的栏目,如果修改栏目,需要修改模板相应的标签。站点内容均可在后台网站基本设置中添加。全站可生成HTML,安装默认动态浏览。并可以独立设置SEO标题、关键字、描述信息。源码包中带有少量测试数据,安装时可选择演示安装或全新安装。如果全新安装,后台内容充实后,首页才能完全显示出来。(全新安装后可以删除演示数据用到的图片,目录在https://

下载

查询软删除的记录:

  • withTrashed()
    这个方法会包含软删除和未软删除的所有记录。

    $allPosts = App\Models\Post::withTrashed()->get(); // 获取所有帖子,包括软删除的
  • onlyTrashed()
    这个方法只会返回那些已经被软删除的记录。

    $deletedPosts = App\Models\Post::onlyTrashed()->get(); // 只获取软删除的帖子

这些方法可以像其他查询作用域一样链式调用:

// 获取所有被软删除,且标题包含“Laravel”的帖子
$specificDeletedPosts = App\Models\Post::onlyTrashed()
                                        ->where('title', 'like', '%Laravel%')
                                        ->get();

恢复软删除的记录:

要将一个被软删除的记录恢复到正常状态,你需要先找到它(使用

withTrashed()
onlyTrashed()
),然后调用
restore()
方法:

$post = App\Models\Post::onlyTrashed()->find(1); // 找到 ID 为 1 的软删除帖子
if ($post) {
    $post->restore(); // 将 deleted_at 字段设置为 NULL,帖子恢复正常
}

你也可以一次性恢复多条记录:

App\Models\Post::onlyTrashed()->where('user_id', 5)->restore(); // 恢复用户 ID 为 5 的所有软删除帖子

彻底移除(强制删除)软删除的记录:

如果你确定要从数据库中永久删除一条记录,而不是仅仅软删除它,你可以使用

forceDelete()
方法。这个方法会绕过软删除机制,直接执行物理删除。

$post = App\Models\Post::find(1); // 找到一个帖子
$post->forceDelete(); // 永久删除它,无论是软删除状态还是正常状态

// 或者,先找到软删除的记录,再强制删除
$deletedPost = App\Models\Post::onlyTrashed()->find(2);
if ($deletedPost) {
    $deletedPost->forceDelete(); // 永久删除 ID 为 2 的软删除帖子
}

记住,

forceDelete()
是一个非常强大的操作,一旦执行,数据就真的找不回来了,所以在使用时务必谨慎。我通常会给这个操作加上严格的权限控制和二次确认机制。

软删除对数据库性能和数据一致性有哪些影响?

软删除确实带来了便利,但它并非没有代价,尤其是在大型应用中,我们得考虑它对性能和数据一致性的潜在影响。

性能方面:

  • 索引的重要性: 正如之前提到的,
    deleted_at
    字段的索引至关重要。没有索引,每次查询都需要对整个表进行全表扫描,这在数据量大的时候会是灾难性的。有了索引,数据库可以快速定位或排除软删除的记录。
  • 查询复杂度: 每次查询实际上都多了一个条件:
    WHERE deleted_at IS NULL
    。虽然现代数据库和ORM(如Eloquent)对此优化得很好,但在极端高并发或复杂查询场景下,这种额外的条件仍然会增加一点点处理开销。不过,这种开销通常远小于物理删除带来的数据恢复成本。
  • 存储空间: 软删除的数据仍然占用数据库空间。如果你的系统有大量的软删除数据,并且你从不清理它们,那么数据库的大小会持续增长。这可能导致备份和恢复时间变长,也可能增加存储成本。所以,定期清理(
    forceDelete()
    )那些确实不再需要、且没有审计价值的旧的软删除数据,是一个不错的实践。

数据一致性方面:

  • 唯一约束的挑战: 这是最常见的坑。一个被软删除的记录,其唯一字段(比如用户邮箱、商品SKU)仍然存在于数据库中。如果你的系统不处理这种情况,尝试创建具有相同唯一字段的新记录时就会报错。
    • 解决方案的考量: 之前提过,可以修改数据库层面的唯一索引,让它只对
      deleted_at IS NULL
      的记录生效。例如,在MySQL中,你可以创建一个部分唯一索引(虽然MySQL原生不支持,但可以通过创建函数索引或在应用程序层处理)。更常见且兼容性更好的做法是,在应用程序层面,在插入新数据前,先查询是否有软删除的记录具有相同的唯一字段,然后根据业务逻辑决定是恢复旧记录、更新旧记录、强制删除旧记录,还是拒绝新记录的创建。
  • 业务逻辑的复杂性: 软删除引入了“已删除但存在”的状态,这要求你的业务逻辑在处理数据时,需要明确区分正常数据、软删除数据和物理删除数据。例如,在用户界面上,你可能需要决定是否向管理员展示软删除的用户,或者在统计报表中是否包含软删除的订单。这会增加一些逻辑判断的复杂性。
  • 外键引用: 当一个记录被软删除时,它所引用的其他记录(例如,一个软删除的订单仍然关联着一个用户)并不会自动解除关联。这通常是好事,因为它保持了数据的完整性。但这也意味着,如果你在查询相关联数据时,需要注意是否要包含那些指向软删除记录的关联。例如,你查询用户列表时,可能不想看到那些只关联了软删除订单的用户。

总的来说,软删除是一个非常实用的功能,它带来的便利性通常远超其潜在的性能和一致性挑战。关键在于理解其工作原理,并在设计数据库和业务逻辑时,充分考虑这些影响并采取相应的策略来规避问题。对我而言,花点时间处理好这些细节,远比未来某个时刻面对无法恢复的数据来得划算。

相关专题

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

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

319

2024.04.09

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

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

277

2024.04.09

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

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

370

2024.04.09

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

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

371

2024.04.10

laravel入门教程
laravel入门教程

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

81

2025.08.05

laravel实战教程
laravel实战教程

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

64

2025.08.05

laravel面试题
laravel面试题

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

67

2025.08.05

mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

665

2023.06.20

php远程文件教程合集
php远程文件教程合集

本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

21

2026.01.22

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Laravel---API接口
Laravel---API接口

共7课时 | 0.6万人学习

PHP自制框架
PHP自制框架

共8课时 | 0.6万人学习

PHP面向对象基础课程(更新中)
PHP面向对象基础课程(更新中)

共12课时 | 0.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号