当前位置:

首页 > 编程开发 > ThinkPHP软删除实现方法详解

ThinkPHP软删除实现方法详解

ThinkPHP实现软删除需在数据表添加delete_time字段用于标记删除状态;2.模型中引入SoftDeleteTrait并配置相关字段即可自动将delete()转为更新操作;3.查询时默认自动排除软删除数据,可用withTrashed()或onlyTrashed()控制是否包含已删除数据;4.恢复数据调用restore()方法即可将delete_time置空;5.彻底删除可调用force()或delete(true)执行物理删除,确保灵活性与数据安全。

ThinkPHP实现软删除需在数据表添加delete_time字段用于标记删除状态;2. 模型中引入SoftDelete Trait并配置相关字段即可自动将delete()转为更新操作;3. 查询时默认自动排除软删除数据,可用withTrashed()或onlyTrashed()控制是否包含已删除数据;4. 恢复数据调用restore()方法即可将delete_time置空;5. 彻底删除可调用force()或delete(true)执行物理删除,确保灵活性与数据安全。

ThinkPHP的软删除怎么实现?ThinkPHP如何标记删除数据?

在ThinkPHP里实现软删除,核心思路其实很简单:我们不在数据库里真正删掉那条数据,而是给它打个“已删除”的标记。通常的做法是,在数据表里加一个 delete_time 字段,当需要“删除”时,就往这个字段里填上当前时间戳,而不是执行 DELETE 语句。这样一来,数据还在,只是被系统逻辑上“隐藏”了。ThinkPHP的ORM对这个功能有非常好的内置支持,用起来非常顺手。

ThinkPHP的软删除怎么实现?ThinkPHP如何标记删除数据?

解决方案

要让你的ThinkPHP应用支持软删除,你需要做几件事。首先,数据库层面得有个字段来承载这个“删除标记”。我通常会用 delete_time,类型设为 DATETIMETIMESTAMP,并且允许为空(NULL)。当数据正常存在时,这个字段就是 NULL;一旦被“删除”,就会被填充上删除时的时间。

接下来是模型层的配置。在你的模型类里,你需要引入 SoftDelete Trait,并指定你用来标记删除的字段名。比如,如果你的模型是 app\model\User

ThinkPHP的软删除怎么实现?ThinkPHP如何标记删除数据?

完成这些配置后,当你对模型实例调用 delete() 方法时,ThinkPHP就不会真的去执行 DELETE FROM table WHERE id = xxx 了。它会悄悄地执行一个 UPDATE table SET delete_time = NOW() WHERE id = xxx 的操作。这感觉就像是给数据贴了个隐形标签,告诉系统:“嘿,这玩意儿暂时别显示了。”

比如,你想“删除”ID为1的用户:

ThinkPHP的软删除怎么实现?ThinkPHP如何标记删除数据?
use app\model\User;

$user = User::find(1);
if ($user) {
    $user->delete(); // 此时,user表的id为1的记录的delete_time字段会被填充
    echo "用户已标记为删除。";
}

是不是很简单?感觉就像是ORM在背后帮你做了个小魔术。

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

说实话,我个人在项目里几乎是能用软删除就用,除非业务逻辑明确要求数据必须物理销毁(比如用户注销,需要符合GDPR等隐私法规时)。为什么呢?

首先,数据安全和可恢复性。这是最直观的好处。手一抖,或者业务逻辑没考虑周全,物理删除的数据就真的没了,想找回来简直是噩梦。但软删除不一样,它只是个标记,你随时可以把它“恢复”回来。想想看,如果一个电商平台,用户不小心删了订单,或者运营人员误删了商品,能一键恢复是多么重要的事情。这就像给你的数据买了一份保险。

其次,审计和追踪。很多时候,我们需要知道数据曾经的存在状态,或者谁在什么时候“删除了”它。软删除保留了数据的完整历史,方便我们进行审计和追踪。这对于金融、医疗等合规性要求高的行业尤其重要。

再来,用户体验。现在很多应用都有“回收站”或者“撤销”功能。软删除就是实现这些功能的基石。用户删了东西还能后悔,这种体验是物理删除无法提供的。

当然,软删除也不是万能药。它也有它的“副作用”。最明显的就是数据库体积膨胀。那些被标记为“删除”的数据依然占用存储空间。如果你的数据量非常大,并且有大量的软删除数据,可能会对数据库性能造成轻微影响,尤其是在没有正确索引的情况下。另外,查询的时候,如果需要排除软删除数据,可能会稍微增加查询复杂度(虽然ThinkPHP已经帮你处理好了)。但通常来说,这些问题在大多数应用场景下都是可控的,收益远大于成本。

如何查询包含或排除软删除的数据?

既然数据只是被标记了,那在查询的时候,系统怎么知道哪些是“正常”的,哪些是“已删除”的呢?ThinkPHP的软删除功能非常智能,它默认的行为就是自动排除那些 delete_time 不为 NULL 的记录。这意味着,你平时写查询,比如 User::where('status', 1)->select();,它返回的就已经是“未删除”的数据了。

但有时候,我们就是需要看到那些“已删除”的数据,比如在后台管理系统里,管理员可能需要查看所有数据,包括被删除的,或者只是想看看哪些数据被删了。ThinkPHP提供了几个非常方便的方法来控制查询行为:

  • 查询所有(包括软删除数据): 使用 withTrashed() 方法。

    use app\model\User;
    
    // 获取所有用户,包括那些已经被软删除的
    $allUsers = User::withTrashed()->select();
    // 这会生成类似 SELECT * FROM user WHERE delete_time IS NULL OR delete_time IS NOT NULL 的查询,或者更直接的 SELECT * FROM user
  • 只查询软删除数据: 使用 onlyTrashed() 方法。这在你想清理回收站或者查看删除历史时特别有用。

    use app\model\User;
    
    // 只获取那些已经被软删除的用户
    $trashedUsers = User::onlyTrashed()->select();
    // 这会生成类似 SELECT * FROM user WHERE delete_time IS NOT NULL 的查询

这些方法可以很灵活地和其他查询条件链式调用,满足你各种复杂的查询需求。比如,你想找某个时间段内被删除的用户:

use app\model\User;

$recentTrashedUsers = User::onlyTrashed()
                            ->where('delete_time', '>', '2023-01-01 00:00:00')
                            ->select();

软删除的数据如何恢复或彻底删除?

软删除的魅力之一就是它的可逆性。既然只是打了个标记,那自然也能把这个标记“擦掉”,让数据重新“活”过来。同时,如果你真的想彻底清理掉一些数据,ThinkPHP也提供了相应的强制删除方法。

  • 恢复软删除的数据: 使用模型实例的 restore() 方法。这会把 delete_time 字段重新设为 NULL

    use app\model\User;
    
    // 假设我们知道某个被软删除的用户的ID是10
    $trashedUser = User::onlyTrashed()->find(10);
    if ($trashedUser) {
        $trashedUser->restore(); // 此时,ID为10的用户的delete_time字段会变回NULL
        echo "用户ID:10 已成功恢复。";
    } else {
        echo "未找到ID为10的已删除用户。";
    }

    你也可以批量恢复,但这需要你先查询出这些被删除的数据集合:

    // 恢复所有在某个时间点后被删除的用户
    User::onlyTrashed()->where('delete_time', '>', '2023-06-01 00:00:00')->restore();
  • 彻底删除(物理删除)软删除的数据: 有时候,你确实需要把数据从数据库里彻底抹掉,比如为了节省空间,或者出于合规性考虑。这时,你可以使用模型实例的 force() 方法,或者在 delete() 方法中传入 true 参数。

    use app\model\User;
    
    // 方式一:使用force()方法
    $userToDeletePermanently = User::onlyTrashed()->find(5); // 找到一个已被软删除的用户
    if ($userToDeletePermanently) {
        $userToDeletePermanently->force(); // 此时,ID为5的记录会被从数据库中物理删除
        echo "用户ID:5 已被物理删除。";
    }
    
    // 方式二:在delete()方法中传入true
    $anotherUserToDelete = User::find(6); // 找到一个正常的用户
    if ($anotherUserToDelete) {
        $anotherUserToDelete->delete(true); // 此时,ID为6的记录会被直接物理删除,不会走软删除逻辑
        echo "用户ID:6 已被物理删除。";
    }

    值得注意的是,delete(true) 这种方式,无论你的模型是否开启了软删除,都会直接执行物理删除。而 force() 方法通常是在你已经查询出被软删除的数据后,再决定对其进行物理删除的操作。

在实际项目中,我通常会结合定时任务来清理那些“超期”的软删除数据,比如设置一个策略:被软删除超过90天的数据,就自动执行物理删除,这样既保证了短期内的数据可恢复性,又避免了数据库无限膨胀。这是一种比较平衡的做法。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发
相关文章 更多
C++动态数组初始化怎么写?常用语句与代码示例
C++动态数组初始化怎么写?常用语句与代码示例

深入解析C++中动态数组的初始化机制,涵盖new操作符的不同用法、基本类型与类对象的初始化差异,以及为何在现代C++开发中应优先使用std::vector。

using namespace 使用中遇到的问题怎么解决
using namespace 使用中遇到的问题怎么解决

命名空间的基本概念与常见引入问题在C++等编程语言中,命名空间(namespace)是一种将代码标识符(如变量、函数、类名)封装在特定名称下的机制,其主要目的是避免命名冲突,尤其是在大型项目或使用多个第三方库时。使用“using namespace”指令可以将指定命名空间中的所有名称引入当前作用域,

c语言函数递归 实操经验总结:这些技巧很实用
c语言函数递归 实操经验总结:这些技巧很实用

理解递归的基本原理在C语言中,递归是一种函数调用自身的编程技术。要掌握它,首先需要理解其核心思想:将一个复杂的大问题,分解为一个或几个与原问题相似但规模更小的子问题,直到子问题足够简单,可以直接求解。这个过程通常包含两个关键部分:递归出口和递归体。递归出口定义了问题何时不再继续分解,即最简单、可直接

c语言函数递归 怎么选?常见方案对比分析
c语言函数递归 怎么选?常见方案对比分析

递归函数的基本概念与适用场景在C语言编程中,递归是一种函数调用自身的编程技巧。它并非适用于所有问题,但在处理某些具有自相似结构的问题时,能提供极其清晰和优雅的解决方案。递归的核心思想是将一个大规模问题分解为一个或多个同类型但规模更小的子问题,直到子问题简单到可以直接求解。典型的适用场景包括树形结构的

Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解
Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解

理解内存管理的基石在Objective-C的编程世界中,内存管理是开发者必须掌握的核心技能之一。它直接关系到应用的性能、稳定性与资源利用效率。与一些采用自动垃圾回收机制的语言不同,Objective-C在很长一段时间里,依赖一套基于引用计数的、需要开发者部分介入的管理规则。这套规则的核心思想是明确的

如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏
如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏

理解 dealloc 的角色与时机在 iOS 应用开发中,内存管理是保障应用性能与稳定性的基石。dealloc 方法是 Objective-C 中对象生命周期结束时的关键回调,它标志着对象即将被系统回收内存。正确理解其触发时机至关重要:当一个对象的引用计数降为零时,运行时系统会自动调用该对象的 de

深入理解 Objective-C 中的 dealloc 方法:内存管理核心机制
深入理解 Objective-C 中的 dealloc 方法:内存管理核心机制

内存管理的基石在Objective-C的世界里,内存管理是开发者必须掌握的核心技能之一。作为一门在手动引用计数(MRC)时代诞生的语言,Objective-C要求程序员对对象的生命周期有清晰的认识。dealloc方法正是这一生命周期中至关重要的终点站。它是一个实例方法,当对象的引用计数降为零时,系统

理解 native2ascii:Java 国际化开发中的字符编码工具
理解 native2ascii:Java 国际化开发中的字符编码工具

native2ascii 工具的基本定位在Ja va应用程序的国际化与本地化开发过程中,处理非拉丁字符集是一个常见且关键的环节。Ja va内部使用Unicode字符集来统一表示全球各种语言的文字,但其属性文件(.properties)在历史上要求使用ASCII编码,或者更准确地说,要求非ASCII字

如何使用 native2ascii 转换中文字符为 Unicode 转义序列
如何使用 native2ascii 转换中文字符为 Unicode 转义序列

理解 native2ascii 工具的基本用途在软件开发,特别是涉及国际化处理的场景中,开发者常常需要处理不同编码的文本资源。native2ascii 是 Ja va 开发工具包(JDK)中提供的一个命令行实用程序,其主要功能是将包含本地字符编码(非ASCII字符)的文件,转换为包含 Unicode

Java native2ascii 命令详解:解决属性文件乱码问题
Java native2ascii 命令详解:解决属性文件乱码问题

native2ascii 命令的由来与作用在Ja va开发中,处理国际化资源文件是一个常见需求。资源文件通常以.properties格式存储,用于支持多语言界面。然而,Ja va属性文件默认采用ISO-8859-1字符集编码,这导致了一个直接的问题:当文件中包含非拉丁字符(如中文、日文、韩文等)时,

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件
macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

Mac软件 更多
灵活计算器
灵活计算器
macOS/iOS/Android

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师
macOS

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

WINDOWS 更多
Windows 10
Windows 10
Windows

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘
Windows/macOS/iOS/Android

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。