首页 > php框架 > ThinkPHP > 正文

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

小老鼠
发布: 2025-07-23 15:12:02
原创
728人浏览过

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

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

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

use think\Model;
use think\model\SoftDelete; // 引入软删除Trait

class 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 app\model\User;

$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 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天的数据,就自动执行物理删除,这样既保证了短期内的数据可恢复性,又避免了数据库无限膨胀。这是一种比较平衡的做法。

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

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

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