ThinkAdmin V6 官方文档

💾 更新助手

SaveHelper 是 ThinkAdmin 提供的数据更新助手,专注于简化数据状态的更新操作,如数据禁用、启用以及状态更改等。通过简洁的接口和直观的操作,快速实现数据状态的更新。

📚 基础概念

🤔 基本介绍

SaveHelper(更新助手)是 ThinkAdmin 框架提供的一个工具类,专门用于快速更新数据记录的状态或字段值。

简单理解:就像数据的"状态切换器",帮你快速更新数据的状态,如启用/禁用、上架/下架等。

传统方式(不推荐):

// ❌ 传统方式:需要手动处理更新逻辑
public function state()
{
 $ids = input('id');
 $status = input('status');

 // 1. 验证数据
 if (empty($ids)) {
 $this->error('ID 不能为空');
 }
 if (!in_array($status, [0, 1])) {
 $this->error('状态值范围异常');
 }

 // 2. 批量更新
 $ids = str2arr($ids);
 foreach ($ids as $id) {
 SystemUser::where('id', $id)->update(['status' => $status]);
 }

 $this->success('更新成功');
}

使用 SaveHelper(推荐):

// ✅ 使用 SaveHelper:一行代码完成更新
public function state()
{
 SystemUser::mSave($this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
 ]));
}

🤔 使用优势

问题1:代码重复

不使用 SaveHelper 时,每个状态更新都需要重复编写相同的逻辑:

// ❌ 每个状态更新都要写这些代码
$ids = input('id');
$status = input('status');
// 验证、更新、返回结果... 大量重复代码

问题2:容易出错

手动处理更新逻辑容易出错:

// ❌ 容易出错:忘记验证、忘记处理条件等
$ids = input('id');
SystemUser::whereIn('id', $ids)->update(['status' => $status]);
// 没有验证,可能更新错误的数据

问题3:维护困难

当需要修改更新逻辑时,需要在多个地方修改:

// ❌ 需要在多个控制器中修改相同的逻辑
// UserController.php
SystemUser::whereIn('id', $ids)->update(['status' => $status]);

// OrderController.php
SystemOrder::whereIn('id', $ids)->update(['status' => $status]);
// 重复代码

使用 SaveHelper 的优势:

// ✅ 统一接口,代码简洁
SystemUser::mSave($this->_vali([...]));
SystemOrder::mSave($this->_vali([...]));

🎯 核心功能

功能1:快速更新

一行代码完成数据更新:

// 更新用户状态
SystemUser::mSave($this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
]));

功能2:批量操作

支持批量更新多条记录:

// 批量更新用户状态
// POST 数据:id=1,2,3&status=1
SystemUser::mSave($this->_vali([
 'status.require' => '状态值不能为空!',
]));
// 自动更新 id=1,2,3 的用户状态为 1

功能3:条件限制

支持设置更新条件,确保数据安全:

// 只更新未删除的记录
SystemUser::mSave(
 $this->_vali([...]),
 'id',
 ['is_deleted' => 0] // 更新条件
);

功能4:回调处理

支持前置和后置回调,处理业务逻辑:

// 前置回调:更新前处理
protected function _save_filter($query, array &$data)
{
 // 验证和处理数据
}

// 后置回调:更新后处理
protected function _save_result(bool $result)
{
 // 处理更新结果
}

📖 相关概念

状态字段

  • 用于标识数据状态的字段
  • 例如:status(0=禁用,1=启用)

批量更新

  • 一次性更新多条记录
  • 例如:同时更新多个用户的状态

条件限制

  • 设置更新条件,只更新符合条件的记录
  • 例如:只更新未删除的记录

🎯 使用场景

场景1:用户管理

启用/禁用用户账号:

public function state()
{
 SystemUser::mSave($this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
 ]));
}

场景2:商品管理

上架/下架商品:

public function state()
{
 SystemGoods::mSave($this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
 ]), 'id', ['is_deleted' => 0]);
}

场景3:订单管理

审核通过/拒绝订单:

public function audit()
{
 SystemOrder::mSave($this->_vali([
 'audit_status.require' => '审核状态不能为空!',
 'audit_status.in:1,2' => '审核状态范围异常!',
 ]));
}

场景4:内容管理

发布/隐藏文章:

public function publish()
{
 SystemArticle::mSave($this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
 ]));
}

🚀 主要功能

  • 状态更新: 快速更新数据状态(启用/禁用等)
  • 批量处理: 支持批量更新多条数据记录
  • 安全验证: 完善的数据验证和权限控制
  • 错误处理: 详细的错误处理和日志记录
  • 事务支持: 支持数据库事务操作

📋 使用场景

  • 用户状态管理(启用/禁用用户)
  • 商品状态管理(上架/下架商品)
  • 订单状态管理(处理/完成订单)
  • 内容状态管理(发布/隐藏内容)
  • 批量数据操作

⚙️ 工作原理

数据定位

  • 根据传入的数据 ID 和条件自动定位数据记录
  • 支持主键字段和自定义查询条件
  • 确保数据操作的安全性和准确性
  • 支持批量数据定位

状态更新

  • 提供清晰的状态选项供用户选择
  • 自动执行状态更新操作
  • 支持单条和批量数据更新
  • 支持自定义状态值

安全保护

  • 数据验证和权限控制
  • 防止恶意数据修改
  • 详细的操作日志记录
  • 支持操作权限验证

事务处理

  • 支持数据库事务操作
  • 确保数据一致性
  • 支持回滚机制
  • 异常处理机制

具体实现原理

为了充分利用 SaveHelper 数据更新助手在模型(Model)和控制器(Controller)中的功能,系统进行了以下优化:

  • 模型继承:若需在模型中使用 SaveHelper 快捷查询器,该模型应继承 \think\admin\Model 类。这样做可以确保模型拥有 SaveHelper 提供的所有功能,方便进行数据的快速保存和查询操作。
  • 控制器继承:对于需要使用 SaveHelper 快捷查询器的控制器,应继承 \think\admin\Controller 类。通过继承这个基类,控制器可以方便地调用 SaveHelper 的相关方法,实现对数据的快速处理和响应。
  • 前端数据传递:前端需要传递需要修改的数据 ID 以及数据状态值给后端。为了确保数据的安全性和准确性,强烈建议前端传递第二个参数(如操作类型、验证信息等)。这样可以为后端提供更多的上下文信息,有助于后端进行更精确的数据处理和验证。
  • 数据安全考虑:为了防止数据被恶意修改,使用 SaveHelper 时指定第二个参数是非常必要的。此外,还可以结合验证器 _vali() 和限定条件 $where 变量来进一步确保数据的安全性。验证器可以对数据进行严格的校验,确保只有符合规则的数据才能被保存;而 $where 变量则可以限制操作的范围,防止对不应修改的数据进行操作。

通过以上优化,SaveHelper 快捷查询器在模型和控制器中的使用变得更加灵活和安全,同时前端传递的数据也得到了更好的处理和验证,提升了整个系统的稳定性和安全性。

// 1.0 模型用法
// 参数 $data 为待修改数据
// 参数 $field 为主键字段
// 参数 $where 为修改查询条件
SystemUser::mSave($data, $field, $where);

// 1.1 模型通用更新
SystemUser::mSave();

// 1.2 配合验证器使用(推荐方式)
SystemUser::mSave($this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
]));

// 1.3 配置验证器和限制条件
SystemUser::mSave($this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
]), 'id', [
 'is_deleted' => 0,
 'status' => 1,
]);


// 2.0 控制器用法(不推荐,建议使用模型方法)
// 参数 $dbQuery 为模型名称
// 参数 $data 为待修改数据
// 参数 $field 为主键字段
// 参数 $where 为修改查询条件
$this->_save('SystemUser', $data, $field, $where);

// 2.1 通用修改器(不推荐,建议使用模型方法)
$this->_save('SystemUser');

// 2.2 配合验证器使用(不推荐,建议使用模型方法)
$this->_save('SystemUser', $this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
]));

数据回调处理

对于数据更新操作,Controller 内置了两个回调方法:

// 更新前置操作,允许使用引用更改查询条件和数据
// 参数 $query:查询对象
// 参数 $data:待更新的数据数组
// 返回 false 时,默认行为将不会再执行
[_ACTION]_save_filter($query, array &$data)

// 更新后置操作
// 参数 $result:更新结果,成功为 true,失败为 false
// 返回 false 时,默认行为将不会再执行
[_ACTION]_save_result(bool $result)

实际应用案例

<?php
declare(strict_types=1);

namespace app\admin\controller;

use think\admin\Controller;
use think\admin\model\SystemUser;

/**
 * 系统用户管理
 * @class User
 * @package app\admin\controller
 */
class User extends Controller
{
 /**
 * 修改数据状态
 * @auth true 
 */
 public function state()
 {
 // 实际项目中的安全检查示例
 $this->_checkInput();

 SystemUser::mSave($this->_vali([
 'status.in:0,1' => '状态值范围异常!',
 'status.require' => '状态值不能为空!',
 ]));
 }

 /**
 * 检查输入变量(实际项目中的私有方法示例)
 */
 private function _checkInput()
 {
 // 防止删除系统超级账号
 if (in_array('10000', str2arr(input('id', '')))) {
 $this->error('系统超级账号禁止删除!');
 }
 }

 /**
 * 更新前置回调(在更新前进行数据过滤)
 * @param $query 查询对象
 * @param array $data 待更新的数据
 */
 protected function _save_filter($query, array &$data)
 {
 // 可以修改查询条件
 $query->where('is_deleted', 0);

 // 可以修改待更新的数据
 if (isset($data['status'])) {
 // 添加额外的数据
 $data['update_at'] = date('Y-m-d H:i:s');
 }
 }

 /**
 * 更新后置回调(通用回调)
 * @param bool $result 更新结果
 */
 protected function _save_result(bool $result)
 {
 if ($result) {
 sysoplog('系统用户管理', '更新用户状态成功');
 }
 }

 /**
 * 当一个控制器存在多个 save 操作时,可以指定回调前缀
 * @param bool $result 更新结果
 */
 protected function _state_save_result(bool $result)
 {
 // 可以根据 $result 状态返回结果 
 // 失败 $this->error(MESSAGE);
 // 成功 $this->success(MESSAGE);
 }
}

如果是在 `ThinkAdmin` 后台基于 `admin.js` 的情况下,可使用 `data-action` 来与 `SaveHelper` 配合使用。

## 🔧 前端配合使用

**自动状态更新**
```html
<!-- 使用 data-action 属性自动更新状态 -->
<button data-action="{:url('save')}" 
 data-value="id#{{d.id}};status#1" 
 data-confirm="确认要启用这条记录吗?"
 class="layui-btn layui-btn-sm">启用</button>

批量状态更新

<!-- 批量更新多条记录 -->
<button data-action="{:url('save')}"
 data-value="id#1,2,3;status#1"
 data-confirm="确认要批量启用这些记录吗?"
 class="layui-btn layui-btn-sm">批量启用</button>

前端提交格式说明 前端提交上来的内容 data-value 支持多组数据,以英文分号 ; 分隔,键与值以英文 # 分隔,如:data-value="id#1;status#0;"

格式说明:

  • 单条记录:data-value="id#1;status#0"
  • 多条记录:data-value="id#1,2,3;status#1"

SaveHelper 深入应用

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 batchState()
 {
 $data = $this->_vali([
 'ids.require' => '用户ID不能为空!',
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
 ]);

 // 开启数据库事务
 Db::startTrans();
 try {
 // 批量更新用户状态
 SystemUser::mk()
 ->whereIn('id', str2arr($data['ids']))
 ->where('is_deleted', 0)
 ->update(['status' => $data['status']]);

 // 记录操作日志
 sysoplog('系统用户管理', "批量更新用户状态[{$data['status']}]");

 // 提交事务
 Db::commit();
 $this->success('批量更新成功!');
 } catch (\Exception $e) {
 // 回滚事务
 Db::rollback();
 $this->error('批量更新失败:' . $e->getMessage());
 }
 }
}

2. 复杂业务逻辑处理

protected function _save_filter(array &$data)
{
 // 业务规则验证
 if (!empty($data['id'])) {
 $user = SystemUser::mk()->find($data['id']);
 if (empty($user)) {
 $this->error('用户不存在!');
 }

 // 状态变更时的特殊处理
 if ($user['status'] != $data['status']) {
 // 禁用用户时,清除登录会话
 if ($data['status'] == 0) {
 $this->app->session->delete("user_{$data['id']}");
 }

 // 记录状态变更日志
 sysoplog('系统用户管理', "用户[{$user['username']}]状态变更为[{$data['status']}]");
 }
 }
}

protected function _save_result(bool $result)
{
 if ($result) {
 // 触发用户状态变更事件
 $this->app->event->trigger('PluginAdminUserStatusChange', [
 'id' => input('id'),
 'status' => input('status'),
 ]);
 }
}

3. 条件限制和权限控制

public function save()
{
 // 非超级管理员只能更新自己的数据
 $where = [];
 if (!AdminService::isSuper()) {
 $where['uuid'] = AdminService::getUserId();
 }

 SystemUser::mSave(
 $this->_vali([
 'status.require' => '状态值不能为空!',
 'status.in:0,1' => '状态值范围异常!',
 ]),
 'id',
 $where
 );
}

4. 性能优化建议

// 批量更新时,使用 whereIn 而不是循环更新
// ❌ 不推荐:循环更新
foreach ($ids as $id) {
 SystemUser::mk()->where('id', $id)->update(['status' => 1]);
}

// ✅ 推荐:批量更新
SystemUser::mk()
 ->whereIn('id', $ids)
 ->update(['status' => 1]);

// 使用索引字段进行查询
SystemUser::mk()
 ->where('id', $id) // id 是主键,有索引
 ->where('status', 1) // 如果 status 有索引,查询更快
 ->update(['status' => 0]);
  • 多字段更新:data-value="id#1;status#1;name#test"
最近更新:
Contributors: 邹景立, Anyon

AltStyle によって変換されたページ (->オリジナル) /