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:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; // 引入 Trait

class Post extends Model
{
    use SoftDeletes; // 使用 Trait

    // ... 其他模型定义
}

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

现在,当你调用模型的

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

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

常见陷阱:

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

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

下载
  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查询是不会返回这些记录的。你需要一些特殊的方法来操作它们。

查询软删除的记录:

  • 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原生不支持,但可以通过创建函数索引或在应用程序层处理)。更常见且兼容性更好的做法是,在应用程序层面,在插入新数据前,先查询是否有软删除的记录具有相同的唯一字段,然后根据业务逻辑决定是恢复旧记录、更新旧记录、强制删除旧记录,还是拒绝新记录的创建。
  • 业务逻辑的复杂性: 软删除引入了“已删除但存在”的状态,这要求你的业务逻辑在处理数据时,需要明确区分正常数据、软删除数据和物理删除数据。例如,在用户界面上,你可能需要决定是否向管理员展示软删除的用户,或者在统计报表中是否包含软删除的订单。这会增加一些逻辑判断的复杂性。
  • 外键引用: 当一个记录被软删除时,它所引用的其他记录(例如,一个软删除的订单仍然关联着一个用户)并不会自动解除关联。这通常是好事,因为它保持了数据的完整性。但这也意味着,如果你在查询相关联数据时,需要注意是否要包含那些指向软删除记录的关联。例如,你查询用户列表时,可能不想看到那些只关联了软删除订单的用户。

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

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

339

2024.04.09

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

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

293

2024.04.09

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

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

772

2024.04.09

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

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

385

2024.04.10

laravel入门教程
laravel入门教程

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

141

2025.08.05

laravel实战教程
laravel实战教程

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

85

2025.08.05

laravel面试题
laravel面试题

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

80

2025.08.05

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

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

453

2026.03.04

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

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

精品课程

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

共7课时 | 0.7万人学习

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号