thinkphp6.x回收站功能需模型、字段、调用三者严格对齐:数据库加null datetime字段,模型启用softdelete并设$deletetime,查询用onlytrashed(),恢复须先查后调实例restore(),批量恢复优先用模型update()或chunk(),强制删除必须带true参数。

如果您在ThinkPHP6.x中已启用软删除机制,但希望构建一个可视化的数据回收站功能并实现安全恢复逻辑,则需严格遵循模型、字段与调用三者对齐原则。以下是实现该功能的具体路径:
一、数据库字段配置与模型启用
软删除依赖一个可空的时间标记字段,该字段必须存在于对应数据表中,并被模型正确识别。若字段未按规范配置,后续所有回收站展示与恢复操作均将静默失效。
1、执行SQL语句为数据表添加软删除字段:ALTER TABLE user ADD delete_time DATETIME NULL DEFAULT NULL;
2、清空框架运行时缓存目录:runtime/cache/,防止模型因缓存旧结构而忽略新字段。
3、在模型类顶部导入命名空间:use think\model\concern\SoftDelete;
4、在模型类定义中声明trait并启用软删除:use SoftDelete; protected $useSoftDelete = true;
5、显式指定软删除字段名(若非默认):protected $deleteTime = 'delete_time';
6、确保模型未将delete_time纳入自动时间戳字段列表,避免新增记录时即被标记为已删除。
二、回收站数据查询实现
回收站功能的核心是准确筛选出所有已被软删除但尚未物理清除的记录。默认查询会自动过滤掉这些数据,因此必须显式调用专用方法解除过滤条件。
1、在模型中定义回收站查询方法:public function recycle_bin() { return $this->onlyTrashed()->paginate(10); }
2、在控制器中调用该方法获取分页数据:$recycled = UserModel::recycle_bin();
3、在视图中遍历输出时,注意每条记录的delete_time字段值应为非NULL时间戳,否则不属于回收站范围。
4、若需支持搜索或条件筛选,必须将onlyTrashed()置于链式调用最前端:UserModel::onlyTrashed()->where('name', 'like', '%test%')->select();
三、单条数据恢复逻辑
恢复操作本质是将软删除标记字段(如delete_time)重置为NULL,使该记录重新进入常规查询结果集。此过程必须通过模型实例完成,且需前置验证存在性。
1、先通过onlyTrashed()查出目标记录:$user = UserModel::onlyTrashed()->find(123);
2、判断记录是否存在,避免对空对象调用方法:if ($user) { $user->restore(); }
3、检查restore()返回值以确认执行结果:if (false === $user->restore()) { /* 字段不可空或权限异常 */ }
4、恢复成功后,该记录仍不会出现在UserModel::select()中,除非重新执行查询——恢复不自动刷新当前查询结果。
四、批量恢复的两种实现方式
ThinkPHP原生不提供restoreAll()方法,批量恢复必须根据是否需要触发模型事件进行路径选择。绕过模型虽快,但丢失钩子与校验能力。
1、走模型逻辑并触发restoring/restored事件:UserModel::onlyTrashed()->chunk(500, function ($items) { $items->each->restore(); });
2、跳过模型层直接更新数据库字段(无事件、无校验):Db::name('user')->where('delete_time', 'not null')->update(['delete_time' => null]);
3、使用模型批量更新语法(TP6.x支持):UserModel::onlyTrashed()->update(['delete_time' => null]);
4、若字段为BIGINT类型,需在模型中声明类型映射:protected $type = ['delete_time' => 'integer'];,否则NULL写入可能被转为0导致恢复无效。
五、真实删除(从回收站彻底清除)
当用户确认某条数据无需保留时,需执行物理删除。此操作不可逆,必须启用强制删除标志,并确保调用路径符合模型约束。
1、通过模型静态方法执行强制删除:UserModel::destroy(123, true);
2、或先查出再调用实例方法:$user = UserModel::onlyTrashed()->find(123); if ($user) $user->force()->delete();
3、禁止使用Db::name('user')->delete(123),该写法完全绕过软删除机制,直接物理删除且无日志、无钩子。
4、强制删除前,务必确认该记录确属软删除状态,否则force()->delete()对正常数据同样生效,造成误删。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











