0

0

Laravel模型软删除?软删除怎样实现?

月夜之吻

月夜之吻

发布时间:2025-09-13 08:22:01

|

214人浏览过

|

来源于php中文网

原创

Laravel软删除通过添加deleted_at字段标记删除状态,实现数据可恢复;需在迁移中添加softDeletes()并引入SoftDeletes Trait;查询默认忽略软删除数据,可用withTrashed()或onlyTrashed()获取全部或仅软删除记录;恢复用restore(),永久删除用forceDelete();注意唯一约束冲突、关联模型处理及数据合规性问题。

laravel模型软删除?软删除怎样实现?

Laravel的软删除,简单来说,就是一种“假删除”机制。它不会真的从数据库里把数据抹掉,而是给记录打上一个“已删除”的标记。具体实现上,就是在你的数据库表里加一个

deleted_at
字段,然后通过在模型里引入一个
SoftDeletes
Trait来管理这个字段,让Laravel知道哪些记录是“活”的,哪些是“死”的。这样,你随时都能把那些“死”了的数据“复活”过来,或者彻底清除。

解决方案

要实现Laravel模型的软删除,你主要需要做两件事:更新数据库结构和修改对应的模型。

首先,你需要为你的数据表添加一个

deleted_at
字段。这个字段通常是一个
TIMESTAMP
类型,并且允许为
NULL
。Laravel的迁移文件提供了一个很方便的方法来做这件事:

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

如果你是在创建新表,也可以直接在

create
方法里加上:

Schema::create('your_table_name', function (Blueprint $table) {
    $table->id();
    // ... 其他字段
    $table->softDeletes(); // 添加 deleted_at 字段
    $table->timestamps();
});

运行完迁移(

php artisan migrate
)后,你的表结构就准备好了。

接着,你需要告诉Laravel你的模型要使用软删除功能。这通过在模型中引入

Illuminate\Database\Eloquent\SoftDeletes
Trait来完成。

现在,当你对

YourModelName
的实例调用
delete()
方法时,Laravel就不会执行
DELETE FROM ...
语句了。它会转而更新
deleted_at
字段,将其设置为当前时间戳。这样,这条记录就被“软删除”了。

默认情况下,所有通过Eloquent查询

YourModelName
的语句,都会自动排除那些
deleted_at
不为
NULL
的记录。这意味着,你不需要额外修改你的查询逻辑,就能只获取到“未删除”的数据。

Laravel软删除与硬删除有什么区别?何时选择软删除更合适?

这两种删除方式,核心差异在于数据是否真的从数据库中消失。硬删除(或者叫永久删除)就像是把文件彻底粉碎,不留痕迹;而软删除则更像是把文件移到了回收站,虽然看不见了,但它还在那里,随时可以恢复。

硬删除

  • 特点:数据从数据库中永久移除,不可恢复。
  • 适用场景
    • 临时数据或无用数据:比如用户会话、日志文件(如果不需要长期保存)。
    • 满足某些合规性要求:例如GDPR中的“被遗忘权”,当用户要求彻底删除其个人数据时,硬删除可能是必需的。
    • 性能优化:对于非常大的表,硬删除可以减少表大小,理论上提升查询性能,尽管现代数据库优化得很好,这种影响通常很小。

软删除

  • 特点:数据仍在数据库中,只是被标记为“已删除”,可以恢复。
  • 适用场景
    • 重要业务数据:订单、用户账户、文章、评论等,这些数据通常有恢复需求,或者需要保留历史记录以供审计。
    • 防止误操作:用户或管理员不小心删除了数据,可以通过恢复功能挽回损失。
    • 审计和历史记录:保留数据的完整生命周期,可以追踪数据何时被删除,由谁删除(如果配合其他字段)。
    • 复杂业务逻辑:某些业务流程可能需要区分“活跃”和“已删除”状态,但又不想完全丢失数据。

在我看来,除非有明确的理由必须硬删除,我通常会倾向于使用软删除。它提供了一个很好的安全网,很多时候能避免一些不必要的麻烦。想想看,如果一个用户不小心删除了他们辛苦编辑的文章,你却告诉他们“抱歉,数据没了”,这体验得多糟糕?软删除能很好地解决这类问题。当然,这也会带来一些小小的“代价”,比如数据库体积可能会略微增大,或者在处理唯一约束时需要多考虑一步。

如何在Laravel中查询、恢复和永久删除软删除的数据?

一旦你的模型启用了软删除,Laravel提供了一套非常直观的方法来管理这些“已删除”的记录。

1. 查询软删除的数据:

默认情况下,所有Eloquent查询都会自动排除软删除的记录。如果你想查询包含软删除记录的所有数据,或者只查询软删除的记录,你需要使用特定的方法。

  • 查询所有(包括软删除和未删除):

    use App\Models\YourModelName;
    
    $allRecords = YourModelName::withTrashed()->get();
    // 比如:$posts = Post::withTrashed()->where('user_id', 1)->get();

    withTrashed()
    方法会修改查询,使其包含
    deleted_at
    不为
    NULL
    的记录。

    简单库存管理系统
    简单库存管理系统

    本系统是一个基于工厂模式的三层架构项目,基于VS2005 开发,结构简洁,配合动软Codematic代码生成器,可以使开发效率事半功倍,倍感轻松。本系统主要功能 1,物品类别管理 实现了物品类别的添加、修改、删除功能,方便库存物品分类管理。 2,物品管理 实现物品添加、修改,管理员可实时对物品做出库、入库记录,也可查看详细历史出入库记录。 3,商家管理 实现商家添加、修改、删除功能,方便公司和客户

    下载
  • 只查询软删除的记录:

    use App\Models\YourModelName;
    
    $onlyTrashedRecords = YourModelName::onlyTrashed()->get();
    // 比如:$deletedUsers = User::onlyTrashed()->get();

    onlyTrashed()
    方法则只返回那些
    deleted_at
    不为
    NULL
    的记录。

2. 恢复软删除的数据:

恢复操作同样简单,直接对一个软删除的模型实例调用

restore()
方法即可。

use App\Models\YourModelName;

// 假设我们有一个被软删除的记录
$deletedRecord = YourModelName::onlyTrashed()->find(1); // 找到ID为1的软删除记录

if ($deletedRecord) {
    $deletedRecord->restore(); // 这会将 deleted_at 字段设置为 NULL
    // 现在 $deletedRecord 已经恢复,可以通过常规查询找到
}

// 你也可以批量恢复
YourModelName::withTrashed()->where('status', 'pending')->restore();

restore()
方法会将
deleted_at
字段重新设置为
NULL
,从而使记录再次“可见”。

3. 永久删除(硬删除)数据:

如果你真的想彻底移除一条记录,即使它启用了软删除,你也可以使用

forceDelete()
方法。

use App\Models\YourModelName;

// 假设我们要彻底删除一个记录
$recordToForceDelete = YourModelName::find(1); // 找到一个未删除的记录

if ($recordToForceDelete) {
    $recordToForceDelete->forceDelete(); // 永久删除,不经过软删除流程
}

// 或者,如果你想永久删除一个已经被软删除的记录
$softDeletedRecord = YourModelName::onlyTrashed()->find(2);

if ($softDeletedRecord) {
    $softDeletedRecord->forceDelete(); // 永久删除
}

// 批量永久删除软删除的记录
YourModelName::onlyTrashed()->where('created_at', '<', now()->subMonths(6))->forceDelete();

forceDelete()
会绕过软删除机制,直接执行数据库的
DELETE
语句。这是一个很危险的操作,所以在使用前一定要三思。我个人在使用
forceDelete()
时都格外小心,通常只用于清理那些确定不需要恢复的、过期的软删除数据。

使用Laravel软删除时需要注意哪些潜在问题或最佳实践?

软删除虽然好用,但也不是万能的,它有一些自己的“脾气”和需要注意的地方。

1. 唯一约束(Unique Constraints)的问题: 这是一个我个人踩过几次坑的地方。当你在数据库表中设置了唯一约束(比如用户邮箱

email
字段是唯一的),如果一个用户账户被软删除了,那么他的邮箱还在数据库里。这时,如果另一个新用户尝试注册并使用了这个已被软删除的邮箱,数据库的唯一约束就会报错。

解决方案: 你需要在数据库迁移中,为

deleted_at
字段也加上索引,并且在唯一约束上做一些调整。在Laravel的验证规则中,你可以这样处理:

// 在你的验证规则中
'email' => [
    'required',
    'email',
    Rule::unique('users')->where(function ($query) {
        return $query->whereNull('deleted_at'); // 只有当 deleted_at 为 NULL 时才检查唯一性
    }),
],

或者,更直接一点,你可以在数据库层面创建复合唯一索引,将

email
deleted_at
字段一起作为唯一约束,但要确保
deleted_at
是可空的。

2. 性能考量: 软删除会给你的查询语句增加一个

WHERE deleted_at IS NULL
的条件。对于大多数应用来说,这个额外条件对性能的影响微乎其微,因为
deleted_at
字段通常会被自动索引。但如果你的表数据量非常巨大,并且软删除的记录占了很大一部分,或者你频繁使用
withTrashed()
进行复杂查询,那么可能需要考虑索引优化。确保
deleted_at
字段有索引,这几乎是标配。

3. 关联关系(Relationships)的处理: 软删除一个父模型时,它的子模型并不会自动被软删除。例如,你软删除了一篇文章(Post),但与这篇文章关联的评论(Comments)并不会自动被软删除。这可能会导致“孤儿”数据,或者在查询时出现不一致。

解决方案

  • 手动处理:在父模型的

    deleting
    事件监听器中,手动软删除所有关联的子模型。

    // 在 Post 模型中
    protected static function boot()
    {
        parent::boot();
    
        static::deleting(function($post) {
            $post->comments()->each(function($comment) {
                $comment->delete(); // 软删除所有关联评论
            });
        });
    
        static::restoring(function($post) {
            $post->comments()->withTrashed()->each(function($comment) {
                $comment->restore(); // 恢复所有关联评论
            });
        });
    }
  • 数据库级联删除:这通常用于硬删除,但如果你真的需要,也可以考虑,但软删除的场景下不太推荐。

  • 业务逻辑判断:在查询子模型时,总是确保父模型未被软删除。

4. 数据存储与合规性: 软删除的数据仍然占用数据库空间。如果你的应用需要遵守GDPR或其他数据隐私法规,要求数据在一定时间后必须被彻底删除,那么仅仅软删除是不够的。你可能需要定期运行任务,对那些已经软删除很长时间的数据执行

forceDelete()
,或者将它们归档到其他存储介质。

5. 用户界面(UI)的清晰性: 如果你的应用允许用户删除内容,最好在UI上明确告知他们数据是软删除的,并且可以恢复。这能提升用户体验,避免混淆。

总的来说,软删除是一个非常实用的功能,它为数据操作提供了一个重要的缓冲层。只要我们清楚它的工作原理和潜在的“陷阱”,并采取相应的措施,它就能极大地简化我们的开发工作,并提升应用的健壮性。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2816

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1691

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1549

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

1036

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1485

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1256

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1589

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1307

2023.11.13

C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

10

2026.01.23

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 9.2万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 10.1万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

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

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