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

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,并指定你用来标记删除的字段名。比如,如果你的模型是 appmodelUser

立即学习“PHP免费学习笔记(深入)”;

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

<?phpnamespace appmodel;use thinkModel;use thinkmodelSoftDelete; // 引入软删除Traitclass User extends Model{    // 使用软删除Trait    use SoftDelete;    // 定义软删除字段,默认是delete_time,如果你的字段名不同,需要在这里指定    // protected $deleteTime = 'delete_time'; // 如果字段名就是delete_time,可以省略这行    // 定义时间戳字段名,如果你的表里有create_time和update_time,通常也需要定义    protected $createTime = 'create_time';    protected $updateTime = 'update_time';    // 如果你的主键不是id,也要在这里指定    // protected $pk = 'user_id';}

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

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

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

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

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

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

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

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

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

如知AI笔记 如知AI笔记

如知笔记——支持markdown的在线笔记,支持ai智能写作、AI搜索,支持DeepseekR1满血大模型

如知AI笔记 27 查看详情 如知AI笔记

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

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

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

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

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

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

use appmodelUser;// 获取所有用户,包括那些已经被软删除的$allUsers = User::withTrashed()->select();// 这会生成类似 SELECT * FROM user WHERE delete_time IS NULL OR delete_time IS NOT NULL 的查询,或者更直接的 SELECT * FROM user

只查询软删除数据:使用 onlyTrashed() 方法。这在你想清理回收站或者查看删除历史时特别有用。

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

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

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

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

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

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

use appmodelUser;// 假设我们知道某个被软删除的用户的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 appmodelUser;// 方式一:使用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天的数据,就自动执行物理删除,这样既保证了短期内的数据可恢复性,又避免了数据库无限膨胀。这是一种比较平衡的做法。

以上就是ThinkPHP的软删除怎么实现?ThinkPHP如何标记删除数据?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/425161.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
让数据库变快的10个建议
上一篇 2025年11月7日 11:10:01
【VC++】字符串详解&窗口&第一个windows程序
下一篇 2025年11月7日 11:10:09

相关推荐

  • 2K正式发表《NBA 2K26》 9月5日发售

    2k正式发表《nba 2k26》,预定9月5日登陆ps5、ps4、xboxs、xbox one、switch2、switch、pc平台。 Shai Gilgeous-Alexander、Angel Reese、Carmelo Anthony分别担任标准版、WNBA版、超级巨星版封面人物。 以上就是2…

    2026年8月26日
    000
  • java中new一个对象的返回 new操作返回对象引用原理

    new操作符在java中通过四步返回对象引用:1.内存分配:jvm在堆内存中为对象分配空间;2.初始化:jvm对内存进行初始化;3.构造函数调用:jvm调用构造函数;4.返回引用:new操作符返回指向新对象的引用。 在Java中,new操作符用于创建一个新对象,并返回该对象的引用。这是一个看似简单却…

    2026年8月26日
    000
  • Workerman如何与Laravel/Symfony集成?

    Workerman如何与Laravel/Symfony集成?这个问题实际上涉及到如何将一个高性能的PHP WebSocket服务器与现代PHP框架进行无缝集成。让我从这个角度出发,详细展开这方面的讨论。 好的,那么我们就来聊聊如何将Workerman与Laravel或Symfony集成吧。我会从实际…

    2026年8月26日
    100
  • 抖音直播怎么投屏?如何把手机直播投屏到电视上

    在如今这个信息爆炸的时代,抖音直播已经成为人们生活中不可或缺的一部分。无论是明星、网红还是普通用户,都在抖音上分享自己的生活和才艺。而在观看抖音直播时,很多人都会遇到一个问题:如何将手机屏幕上的直播内容投屏到电视或其他大屏幕上?下面,我就来为大家详细讲解一下抖音直播怎么投屏。 一、投屏方式概述 抖音…

    2026年8月26日
    000
  • java中mapper层的作用 mapper在MyBatis中的功能解析

    在java中,mapper层在mybatis框架中负责将数据库操作映射到java对象上。具体作用包括:1.定义与数据库交互的接口,包含crud操作;2.通过xml文件或注解将sql语句与java方法关联,实现代码与sql的分离;3.支持动态sql,适应复杂查询需求。 让我们从一个简单的问题开始:在J…

    2026年8月26日
    000
  • AI一键操控更便捷 京东携手荣耀发布畅玩70 Plus新品

    AI一键操控更便捷 京东携手荣耀发布畅玩70 Plus新品AI一键操控更便捷 京东携手荣耀发布畅玩70 Plus新品AI一键操控更便捷 京东携手荣耀发布畅玩70 Plus新品AI一键操控更便捷 京东携手荣耀发布畅玩70 Plus新品

    8月8日,京东联合荣耀在北京南苑森林湿地公园举办了一场别开生面的新品发布会,主题为“用心唤起 ai生活”。此次发布的主角是双方共同打造的全新大屏ai手机——荣耀畅玩70 plus 8gb+256gb(以下简称“荣耀畅玩70 plus”)。这款手机不仅在现场吸引了大量周边居民参与体验,还同步在京东平台…

    2026年8月26日 用户投稿
    000
  • 告别阻塞等待:使用Composer和GuzzlePromises玩转PHP异步编程

    最近在开发一个处理用户提交数据的程序时,遇到了一个棘手的问题:用户输入的文本中包含各种非ASCII字符,例如中文、日文、特殊符号等等。这些字符导致程序在处理字符串时效率低下,甚至出现错误。为了解决这个问题,我尝试了多种方法,最终找到了voku/portable-ascii这个库。Composer在线…

    用户投稿 2026年8月26日
    200
  • Windows中Loader Lock引起的死锁问题

    在程序开发中,常见的做法是将程序模块化,通常实现为动态链接库(dll)。在主程序启动时,可以通过隐式或显式的方式加载这些动态链接库。然而,在windows系统中,如果动态链接库的dllmain函数编写不当,可能会导致一些意想不到的bug,例如典型的loader lock死锁问题。这是一个许多wind…

    2026年8月26日
    000
  • PHP如何安全地生成Akamai授权令牌?matricali/akamai-token-auth助你轻松实现内容保护

    最近在开发一个内容分发平台时,我们选择使用Akamai作为CDN服务商,以确保全球用户都能快速、稳定地访问我们的独家视频内容。然而,一个核心的安全需求摆在了我们面前:这些视频必须是付费用户才能观看,并且我们希望对观看权限进行进一步的限制,比如限制在特定IP地址、或者在一定时间内有效。 一开始,我们尝…

    用户投稿 2026年8月26日
    100
  • 依赖注入(DI)容器设计

    依赖注入容器是一种管理和注入对象依赖的工具,提升代码可维护性和灵活性。设计高效di容器需考虑:1. 生命周期管理(单例、瞬时、范围);2. 依赖解析(处理复杂关系图);3. 配置灵活性(支持多种配置方式);4. 性能优化(缓存、延迟加载、并行解析)。 依赖注入(DI)容器是现代软件开发中一个关键的设…

    2026年8月26日
    000
  • java中文乱码怎么解决 中文编码问题的排查与修复

    %ignore_a_1%是由于字符编码不一致导致的。解决方法包括:1. 源代码编码设置为utf-8;2. 编译时使用-encoding参数指定utf-8;3. 运行时设置系统属性file.encoding为utf-8;4. 数据库和web应用编码设置为utf-8。 解决Java中文乱码问题是每个开发…

    2026年8月26日
    100
  • 数智融合为天津高质量发展注入新动能

    7月31日,以“数智世界津门有为”为主题的“华为中国行2025·天津新质生产力城市峰会”在天津成功举办。在峰会期间的媒体沟通会上,华为天津政企业务总经理叶紫阳全面分享了华为在本地的技术落地成果与生态合作进展,深入阐述了如何通过数智化转型驱动区域新质生产力的高质量发展。 多场景落地构建四大行业“天津范…

    2026年8月26日
    100
  • win11系统提示管理员权限不足_win11获取最高权限的完整教程

    win11系统提示管理员权限不足_win11获取最高权限的完整教程win11系统提示管理员权限不足_win11获取最高权限的完整教程win11系统提示管理员权限不足_win11获取最高权限的完整教程win11系统提示管理员权限不足_win11获取最高权限的完整教程

    要解决win11管理员权限不足的问题,可以采取以下措施:1. 以管理员身份运行程序;2. 调整uac设置降低敏感度;3. 获取受限制文件或文件夹的所有权;4. 确认当前账户为管理员类型;5. 启用隐藏的内置管理员账户临时解决问题;6. 通过注册表修改提升权限但需谨慎操作。权限问题通常源于uac机制限…

    2026年8月26日 用户投稿
    000
  • ai如何修改虚线描边

    在利用ai进行图形创作时,虚线描边是一种极为常见的视觉处理手法,能够为设计元素增添别具一格的艺术感。熟练掌握虚线描边的调整技巧,有助于我们更自由地实现多样化的创意表达。 首先启动AI软件,绘制或导入需要添加虚线描边的对象。选中目标图形后,前往顶部菜单栏选择“窗口”,然后打开“外观”面板。该面板将清晰…

    2026年8月26日
    100
  • 周鸿祎感慨国产GPU AI芯片追赶速度令人惊叹:NVIDIA做了30年 华为才做几年

    7月20日消息,近日,360集团创始人兼董事长周鸿祎发布视频对此进行解读,称黄仁勋携h20芯片再度进入中国市场,释放出中美在ai领域竞争加剧的信号。 从产业层面来看,黄仁勋的多次表态透露出几个重要趋势。其一是全球AI芯片格局正在发生变化,尽管NVIDIA依然占据主导地位,但华为等中国企业的进步速度不…

    2026年8月26日
    000
  • 360浏览器官网入口 360浏览器在线登录链接

    360浏览器官网入口是https://browser.360.cn/,提供登录管家、AI搜索、PDF工具、OCR截图识别等功能,基于Chromium132内核,支持双核切换与云同步服务。 360浏览器官网入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来360浏览器在线登录链接,感兴趣的…

    2026年8月26日
    000
  • 如何实现API接口的幂等性?

    实现api接口的幂等性可以通过以下方法:1. 使用唯一标识,如请求id,确保重复请求返回相同结果;2. 状态控制,通过检查订单状态避免重复操作;3. 乐观锁,利用版本号在并发场景下保证幂等性;4. 版本控制,确保请求版本匹配后才处理请求。这些方法各有优劣,需结合具体业务场景选择和优化。 实现API接…

    2026年8月26日
    000
  • 如何利用Java使用ConcurrentHashMap处理并发

    ConcurrentHashMap因分段锁和CAS机制提升并发性能,支持原子操作如putIfAbsent、compute、merge,遍历时提供弱一致性视图,适用于高并发场景。 在多线程环境中,ConcurrentHashMap 是 Java 提供的一个高效且线程安全的 Map 实现。它比传统的 H…

    2026年8月26日
    000
  • java中文乱码在线转换 在线工具解决编码问题

    java中文乱码可以通过在线工具解决。1) 使用编码转换工具如convertio,将文件从一种编码转换为另一种。2) 使用编码检测工具如fileformat.info,识别未知编码的文件。3) 统一编码标准,使用版本控制和定期检查,确保编码一致性。 提到Java中文乱码在线转换和解决编码问题,我们首…

    2026年8月26日
    100
  • 解决PHPUnitwithConsecutive弃用难题:seec/phpunit-consecutive-params助你轻松迁移

    PHPUnit 作为 PHP 开发者进行单元测试的利器,其每一次更新都可能带来一些变化。最近,PHPUnit 移除了一个常用的方法: withConsecutive 。这个方法允许开发者针对同一个 Mock 对象的方法,使用不同的参数进行多次断言,在很多场景下非常方便。然而,它的移除给很多开发者带来…

    用户投稿 2026年8月26日
    000

发表回复

登录后才能评论
关注微信