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

37次阅读

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你的模型要使用软删除功能。这通过在模型中引入

IlluminateDatabaseEloquentSoftDeletes

Trait来完成。

<?php  namespace AppModels;  use IlluminateDatabaseEloquentFactoriesHasFactory; use IlluminateDatabaseEloquentModel; use IlluminateDatabaseEloquentSoftDeletes; // 引入 SoftDeletes Trait  class YourModelName extends Model {     use HasFactory, SoftDeletes; // 在这里使用它      // ... 你的其他模型配置 }

现在,当你对

YourModelName

的实例调用

delete()

方法时,Laravel就不会执行

DELETE FROM ...

语句了。它会转而更新

deleted_at

字段,将其设置为当前时间戳。这样,这条记录就被“软删除”了。

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

YourModelName

的语句,都会自动排除那些

deleted_at

不为

NULL

的记录。这意味着,你不需要额外修改你的查询逻辑,就能只获取到“未删除”的数据。

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

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

硬删除

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

软删除

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

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

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

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

1. 查询软删除的数据:

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

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

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

    方法会修改查询,使其包含

    deleted_at

    不为

    NULL

    的记录。

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

    笔魂AI

    笔魂AI绘画-在线AI绘画、AI画图、AI设计工具软件

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

    查看详情 Laravel模型软删除?软删除怎样实现?

  • 只查询软删除的记录:

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

    方法则只返回那些

    deleted_at

    不为

    NULL

    的记录。

2. 恢复软删除的数据:

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

restore()

方法即可。

use AppModelsYourModelName;  // 假设我们有一个被软删除的记录 $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 AppModelsYourModelName;  // 假设我们要彻底删除一个记录 $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_atNULL 时才检查唯一性     }), ],

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

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上明确告知他们数据是软删除的,并且可以恢复。这能提升用户体验,避免混淆。

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

以上就是Laravel模型软删除?软删除怎样实现?的详细内容,更多请关注php laravel app ai 邮箱 区别 red php laravel NULL timestamp delete 事件 database 数据库 性能优化 ui

php laravel app ai 邮箱 区别 red php laravel NULL timestamp delete 事件 database 数据库 性能优化 ui

text=ZqhQzanResources