🗑️ 删除助手
DeleteHelper 是 ThinkAdmin 提供的快捷删除助手,能够根据提交的数据自动执行软删除或硬删除操作,简化数据删除流程。
📚 基础概念
🤔 基本介绍
DeleteHelper(删除助手)是 ThinkAdmin 框架提供的一个工具类,用于简化数据删除操作。
简单理解:就像数据的"删除器",帮你安全地删除数据,支持软删除和硬删除两种方式。
传统方式(不推荐):
// ❌ 传统方式:需要手动处理删除逻辑
public function remove()
{
$ids = input('id');
// 1. 验证数据
if (empty($ids)) {
$this->error('ID 不能为空');
}
// 2. 安全检查
if (in_array('10000', str2arr($ids))) {
$this->error('系统超级账号禁止删除!');
}
// 3. 批量删除
$ids = str2arr($ids);
foreach ($ids as $id) {
SystemUser::where('id', $id)->delete();
}
$this->success('删除成功');
}使用 DeleteHelper(推荐):
// ✅ 使用 DeleteHelper:一行代码完成删除
public function remove()
{
$this->_checkInput(); // 安全检查
SystemUser::mDelete();
}🔄 删除方式
DeleteHelper 支持两种删除方式,各有特点:
软删除(Soft Delete)
不真正删除数据,只是标记为已删除。
工作原理:
// 软删除:更新 is_deleted 字段
UPDATE system_user SET is_deleted = 1 WHERE id = 1;
// 数据仍然在数据库中,只是标记为已删除优点:
- 数据可恢复,安全性高
- 可以查看删除历史
- 适合重要数据
缺点:
- 占用数据库空间
- 查询时需要过滤已删除的数据
使用场景:
- 用户管理:删除用户账号(建议使用软删除)
- 商品管理:删除商品信息(建议使用软删除)
- 订单管理:删除订单(建议使用软删除)
硬删除(Hard Delete)
真正从数据库中删除数据。
工作原理:
// 硬删除:真正删除数据
DELETE FROM system_user WHERE id = 1;
// 数据从数据库中彻底删除,无法恢复优点:
- 节省数据库空间
- 性能更好
- 数据彻底清除
缺点:
- 数据无法恢复,风险较高
- 不适合重要数据
使用场景:
- 日志清理:清理过期日志(可以使用硬删除)
- 临时数据:删除不需要恢复的临时数据
- 缓存数据:清理缓存数据
🤔 选择建议
DeleteHelper 会自动检测数据表是否有 is_deleted 或 deleted 字段:
自动检测逻辑:
// 1. 检查数据表是否有 is_deleted 或 deleted 字段
if (字段存在) {
// 使用软删除
UPDATE table SET is_deleted = 1 WHERE id = ?;
} else {
// 使用硬删除
DELETE FROM table WHERE id = ?;
}实际例子:
// 表有 is_deleted 字段 → 自动使用软删除
SystemUser::mDelete();
// 执行:UPDATE system_user SET is_deleted = 1 WHERE id = 1;
// 表没有 is_deleted 字段 → 自动使用硬删除
SystemLog::mDelete();
// 执行:DELETE FROM system_log WHERE id = 1;📖 相关概念
级联删除
- 删除主记录时,同时删除关联的子记录
- 例如:删除用户时,同时删除用户的订单
批量删除
- 一次性删除多条记录
- 例如:同时删除多个用户
条件限制
- 设置删除条件,只删除符合条件的记录
- 例如:只删除未使用的权限
🎯 使用场景
场景1:用户管理
删除用户账号(建议使用软删除):
public function remove()
{
// 防止删除系统超级账号
$this->_checkInput();
// 软删除用户(自动检测 is_deleted 字段)
SystemUser::mDelete();
}场景2:商品管理
删除商品信息(建议使用软删除):
public function remove()
{
// 只删除未上架的商品
SystemGoods::mDelete('id', ['status' => 0]);
}场景3:日志清理
清理过期日志(可以使用硬删除):
public function clear()
{
// 硬删除 30 天前的日志(表没有 is_deleted 字段)
SystemLog::mDelete('id', [
'create_at' => ['<', date('Y-m-d H:i:s', strtotime('-30 days'))]
]);
}🚀 主要功能
- 自动判断: 根据数据自动判断执行软删除或硬删除
- 简化操作: 无需编写繁琐的删除逻辑
- 安全删除: 提供安全的数据删除机制
- 灵活配置: 支持多种删除参数配置
- 权限控制: 支持删除前的权限检查
- 数据保护: 防止非法删除操作
📋 删除类型
软删除
- 特点: 数据不会真正删除,只是标记为已删除
- 优势: 数据可以恢复,安全性高
- 适用场景: 重要数据、需要审计的数据
硬删除
- 特点: 数据从数据库中彻底删除
- 优势: 节省存储空间,性能更好
- 适用场景: 临时数据、不需要恢复的数据
⚙️ 使用要求
模型继承
- 模型必须继承自
\think\admin\Model类 - 确保模型能够利用 DeleteHelper 的快捷删除功能
- 简化删除操作的实现过程
控制器继承
- 控制器必须继承自
\think\admin\Controller类 - 方便调用 DeleteHelper 提供的方法
- 实现数据的快速删除
🔒 安全机制
数据验证
- 删除前验证: 在删除操作前进行数据验证
- 权限检查: 结合权限控制机制防止非法删除
- 条件限制: 通过限定条件确保删除安全
参数配置
- 主键字段: 指定数据主键字段
- 限定条件: 设置删除的限定条件
- 安全筛选: 通过条件筛选确保删除安全
调用快捷删除
// 1.0 模型用法(推荐方式)
// 参数 $field 主键字段,默认自动获取
// 参数 $where 限制条件,安全筛选删除
SystemUser::mDelete(string $field, array $where);
// 1.1 模型通用删除
SystemUser::mDelete();
// 1.2 指定数据主键
SystemUser::mDelete('id');
// 1.3 指定数据主键,指定限定条件
SystemUser::mDelete('id', [
'is_deleted' => 0,
'status' => 0,
]);
// 2.0 控制器用法(不推荐,建议使用模型方法)
// 参数 $dbQuery 模型名称
// 参数 $field 主键字段,默认自动获取
// 参数 $where 限制条件,安全筛选删除
$this->_delete('SystemUser', string $field, array $where);
// 2.1 控制器通用删除(不推荐,建议使用模型方法)
$this->_delete('SystemUser');
// 2.2 指定数据主键(不推荐,建议使用模型方法)
$this->_delete('SystemUser', 'id');
// 2.3 指定数据主键,指定限定条件(不推荐,建议使用模型方法)
$this->_delete('SystemUser', 'id', [
'is_deleted' => 0,
'status' => 0,
]);永久 & 硬删除
如果数据表中不存在is_deleted或deleted字段,则为硬删除。
标记 & 软删除
当前数据表中存在is_deleted或deleted字段时,调用DeleteHelper则自动为软删除操作,在列表查询搜索时加上对应的条件就可以显示需要的数据列表。
数据回调处理
对于数据删除操作,Controller 内置了两个回调方法:
// 删除前置操作,允许使用引用更改查询条件
// 参数 $query:查询对象
// 参数 $where:删除条件数组
// 返回 false 时,默认行为将不会再执行
[_ACTION]_delete_filter($query, array &$where)
// 删除后置操作
// 参数 $result:删除结果,成功为 true,失败为 false
// 返回 false 时,默认行为将不会再执行
[_ACTION]_delete_result(bool $result)回调函数规则说明:
[_ACTION]代表执行的具体动作,例如方法名为remove时,[_ACTION]会被替换为_remove- 如果方法名为
removeAuth,则回调函数名为_removeAuth_delete_filter和_removeAuth_delete_result - 通用回调函数名为
_delete_filter和_delete_result(不带动作前缀)
完整示例:
<?php
declare(strict_types=1);
namespace app\admin\controller;
use think\admin\Controller;
use think\admin\model\SystemAuth;
use think\admin\model\SystemUser;
/**
* 系统用户管理
* @class User
* @package app\admin\controller
*/
class User extends Controller
{
/**
* 删除系统用户(实际项目中的完整示例)
* @auth true
*/
public function remove()
{
// 安全检查:防止删除系统超级账号
$this->_checkInput();
// 表单令牌,为防止重复操作,前端使用 data-csrf='{:systoken("remove")}'生成 token
SystemUser::mDelete();
}
/**
* 检查输入变量(实际项目中的私有方法)
*/
private function _checkInput()
{
// 防止删除系统超级账号(ID 为 10000)
if (in_array('10000', str2arr(input('id', '')))) {
$this->error('系统超级账号禁止删除!');
}
}
}
/**
* 系统权限管理
* @class Auth
* @package app\admin\controller
*/
class Auth extends Controller
{
/**
* 删除系统权限(关联数据清理示例)
* @auth true
*/
public function removeAuth()
{
$this->_applyFormToken();
SystemAuth::mDelete();
}
/**
* 删除前置回调(在删除前进行条件过滤)
* @param $query 查询对象
* @param array $where 删除条件
*/
protected function _removeAuth_delete_filter($query, array &$where)
{
// 可以修改查询条件,例如只允许删除未使用的权限
$query->where('status', 0);
// 可以修改删除条件
// $where['is_deleted'] = 0;
}
/**
* 删除结果处理(实际项目中的后处理示例)
* @param bool $result 删除结果
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
protected function _removeAuth_delete_result(bool $result)
{
if ($result) {
// 删除关联的权限节点数据
$where = ['auth' => $this->request->post('id')];
$this->app->db->name('SystemAuthNode')->where($where)->delete();
sysoplog('系统权限管理', "删除权限成功");
$this->success("权限删除成功!", '');
} else {
$this->error("权限删除失败,请稍候再试!");
}
}
}如果是在 ThinkAdmin 后台基于 admin.js 的情况下,可使用 data-action 来与 DeleteHelper 配合使用。
🔧 前端配合使用
单条记录删除
<!-- 使用 data-action 属性自动删除单条记录 -->
<button data-action="{:url('remove')}"
data-value="{{d.id}}"
data-confirm="确认要删除这条记录吗?"
class="layui-btn layui-btn-sm layui-btn-danger">删除</button>批量记录删除
<!-- 批量删除多条记录 -->
<button data-action="{:url('remove')}"
data-csrf="{:systoken('remove')}"
data-rule="id#{key}"
data-confirm="确认要删除选中的记录吗?"
class="layui-btn layui-btn-sm layui-btn-danger">批量删除</button>前端提交格式说明 前端提交上来的主键值支持多个,以英文逗号分隔。表单 CSRF 根据后台是否开启表单令牌而决定要不要配置使用。
格式说明:
- 单条记录:
data-value="1" - 多条记录:
data-value="1,2,3" - 批量操作:
data-rule="id#{key}"({key}会自动搜索表格已选择的checkbox值)
表格工具栏配置
<script type="text/html" id="toolbar">
<!--{if auth('remove')}-->
<a data-action='{:url("remove")}'
data-value="id#{{d.id}}"
data-confirm="确认要删除这条记录吗?"
class="layui-btn layui-btn-sm layui-btn-danger">删除</a>
<!--{/if}-->
</script>DeleteHelper 深入应用
1. 软删除和硬删除
<?php
declare(strict_types=1);
namespace app\admin\controller;
use think\admin\Controller;
use think\admin\model\SystemUser;
use think\facade\Db;
class User extends Controller
{
/**
* 软删除用户(推荐方式)
* @auth true
*/
public function remove()
{
// 使用软删除,只更新 is_deleted 字段
SystemUser::mDelete();
}
/**
* 硬删除用户(物理删除)
* @auth true
*/
public function forceRemove()
{
$ids = str2arr(input('id', ''));
// 开启事务
Db::startTrans();
try {
foreach ($ids as $id) {
// 删除关联数据
$this->app->db->name('SystemUserAuth')->where('uuid', $id)->delete();
// 物理删除用户
SystemUser::mk()->where('id', $id)->delete();
}
Db::commit();
sysoplog('系统用户管理', "硬删除用户成功");
$this->success('删除成功!');
} catch (\Exception $e) {
Db::rollback();
$this->error('删除失败:' . $e->getMessage());
}
}
}2. 级联删除处理
protected function _remove_filter(array &$data)
{
// 删除前的验证和处理
foreach ($data as $id) {
$user = SystemUser::mk()->find($id);
if (empty($user)) {
continue;
}
// 检查是否可以删除
if ($user['id'] == '10000') {
$this->error('系统超级账号禁止删除!');
}
// 检查是否有关联数据
$authCount = $this->app->db->name('SystemUserAuth')
->where('uuid', $id)
->count();
if ($authCount > 0) {
$this->error("用户[{$user['username']}]存在关联数据,无法删除!");
}
}
}
protected function _remove_delete_result(bool $result)
{
if ($result) {
$ids = str2arr(input('id', ''));
// 删除关联数据
foreach ($ids as $id) {
// 删除用户权限关联
$this->app->db->name('SystemUserAuth')
->where('uuid', $id)
->delete();
// 删除用户操作日志(可选)
// $this->app->db->name('SystemOplog')
// ->where('username', $user['username'])
// ->delete();
}
sysoplog('系统用户管理', "删除用户成功");
$this->success('删除成功!');
}
}3. 批量删除优化
public function batchRemove()
{
$ids = str2arr(input('id', ''));
if (empty($ids)) {
$this->error('请选择要删除的记录!');
}
// 开启事务
Db::startTrans();
try {
// 批量删除(使用 whereIn 提高性能)
SystemUser::mk()
->whereIn('id', $ids)
->where('is_deleted', 0)
->where('id', '<>', '10000') // 防止删除超级账号
->update(['is_deleted' => 1]);
// 删除关联数据
$this->app->db->name('SystemUserAuth')
->whereIn('uuid', $ids)
->delete();
Db::commit();
sysoplog('系统用户管理', "批量删除用户成功");
$this->success('批量删除成功!');
} catch (\Exception $e) {
Db::rollback();
$this->error('批量删除失败:' . $e->getMessage());
}
}4. 条件限制删除
public function remove()
{
// 非超级管理员只能删除自己的数据
$where = ['is_deleted' => 0];
if (!AdminService::isSuper()) {
$where['uuid'] = AdminService::getUserId();
}
SystemUser::mDelete('', $where);
}5. 删除性能优化
// ❌ 不推荐:循环删除
foreach ($ids as $id) {
SystemUser::mk()->where('id', $id)->delete();
}
// ✅ 推荐:批量删除
SystemUser::mk()
->whereIn('id', $ids)
->delete();
// 使用索引字段进行查询
SystemUser::mk()
->where('id', $id) // id 是主键,有索引
->where('is_deleted', 0) // 如果 is_deleted 有索引,查询更快
->delete();