快捷表单助手

为了提升数据保存与更新的操作效率,引入了快捷表单助手 FormHelper,它能够根据提交的表单数据自动处理保存与更新操作。这一功能不仅简化了操作流程,还减少了因手动编写代码而产生的错误,从而提高了系统的稳定性和准确性。

为了充分发挥 FormHelper 的功能,在使用上进行了以下优化:

首先,在模型层面,如果需要在模型中使用 FormHelper,那么该模型必须继承自 \think\admin\Model 类。通过这一改动确保了模型具备与 FormHelper 交互的能力,从而能够自动处理表单数据的保存与更新操作。

其次,在控制器层面,若控制器需要利用 FormHelper 来简化表单数据的处理,则该控制器需要继承自 \think\admin\Controller 类。这样的设计使得控制器能够方便地调用 FormHelper 提供的功能,进一步简化了数据处理的流程。

调用快捷表单

// 1.0 模型用法
// 参数 $template 模板文件
// 参数 $field 主键字段
// 参数 $where 查询条件
// 参数 $data 额外数据
MyModel::mForm($template, $field, $where, $data);

// 1.1 模型通用更新
MyModel::mForm();

// 2.0 控制器用法
// 参数 $dbQuery 为模型名称
// 参数 $template 模板文件
// 参数 $field 主键字段
// 参数 $where 查询条件
// 参数 $data 额外数据
$this->_form($dbQuery, $template, $field, $where, $data);

// 2.1 通用修改器
$this->_form('MyModel');

系统进一步简化了控制器中的数据添加与更新操作。现在,控制器仅需通过一行代码 $this->_form('模板名称'); 即可实现数据的快速添加或更新。这一行代码会自动根据提交的表单数据判断是执行添加操作还是更新操作。如果表单数据中包含了指定的主键,那么将执行更新操作;否则,将执行添加记录的操作。

使用了 HttpResponseException 来直接输出响应,这意味着在使用 $this->_form('模板名称'); 时,控制器无需返回任何内容,系统会自动处理输出。 为了满足更多场景的需求,系统还允许在控制器中给模板额外赋值。通过在控制器中设置 $this->username = '变量值';,你可以将变量值传递给模板,并在模板中直接使用 $username 变量。 为了增强数据的灵活性和安全性,系统引入了 callback 操作(参数使用引用)。开发者可以定义 protected function _form_filter(&$data) 方法,在数据添加到数据库之前对数据进行自定义处理或验证。这一功能使得数据在入库前能够进行额外的过滤和校验,提高了数据的质量和安全性。

数据回调处理

对于表单操作,Controller 内置了两个回调方法,如:

// 表单前置操作,允许使用引用更改 data 值
// 参数 $data :会返回待处理的数组,分显示模型和保存模型,也就是 get|post 请求
[_ACTION]_form_filter(array &$data)

// 表单后置操作,返回的 data 为提交的数据
// 参数 $result :为返回保存结果,成功为 true,失败为 false
// 参数 $data :为返回后的数据,默认为带上数据ID,也就是主键,这个与模型定义有关
[_ACTION]_form_result(bool $result, array $data)

以上案例回调函数如果返回 false 时,Controller 默认行为将不会再执行。

数据处理案例

/**
 * 添加拼团
 * @auth true
 */
public function add()
{
    $this->title = '添加拼团';
    // MyModel::mForm('form');
    $this->_form('MyModel', 'form');
}

/**
 * 编辑拼团
 * @auth true
 */
public function edit()
{
    $this->title = '编辑拼团';
    // MyModel::mForm('form');
    $this->_form('MyModel', 'form');
}

/**
 * 添加拼团商品表单处理
 * @param array $data
 * @throws \think\db\exception\DataNotFoundException
 * @throws \think\db\exception\ModelNotFoundException
 * @throws \think\exception\DbException
 */
protected function _form_filter(&$data)
{
    if (empty($data['code'])) $data['code'] = Data::uniqidNumberCode(10);
    if ($this->request->isGet()) {
        $map = ['package_code' => $data['code']];
        $data['list'] = Db::name('StoreGoodsGroupList')->where($map)->select();
    } else {
        if (empty($data['logo'])) $this->error('请上传商品图标图片');
        if (empty($data['image'])) $this->error('请上传商品展示图片');
        if (empty($data['item_number'])) $this->error('请添加套卡包含内容');
        $all = [];
        foreach (array_keys($data['item_number']) as $key) $all[] = [
            'package_code' => $data['code'],
            'goods_code'   => $data['item_code'][$key],
            'goods_type'   => $data['item_type'][$key],
            'goods_title'  => $data['item_title'][$key],
            'goods_number' => $data['item_number'][$key],
        ];
        // 以下是事务的推荐用法,注意闭包传参需要使用 use 传递
        try {
            $this->app->db->transaction(function () use ($data, $all) {
                // 这个闭包里不能出现 Exception ,不然会自动触发回滚。
                // 注意:$this->error() 和 $this->success() 等操作也会触发回滚哦~
                // 其本质也是 throw HttpResponseException,走后面的 catch 直接 throw 处理。
                $map = ['package_code' => $data['code']];
                $this->app->db->name('StoreGoodsGroupList')->where($map)->delete();
                $this->app->db->name('StoreGoodsGroupList')->insertAll($all);
            });
            // 这里可以返回消息,如 $this->error() 或 $this->success() 等操作
        } catch (\think\exception\HttpResponseException $e) {
            // 如果是返回标准响应异常对象,需要直接抛出
            throw $e;
        } catch (\Exception $e) {
            // 事务执行失败,会触发这里
            $this->error("商品详情处理失败,{$e->getMessage()}");
        }
    }
}

/**
 * 表单结果处理
 * @param boolean $result
 */
protected function _form_result(bool $result,array $data)
{   
    // 这里可以获取到数据记录ID    
    //  echo $data['id']
    if ($result && $this->request->isPost()) {
        $this->success('商品编辑成功!', 'javascript:history.back()');
    }
}

如果是在 ThinkAdmin 后台基于 admin.js 的情况下,可使用 form[data-auto] 来与 $this->_form 配合使用。

Last Updated:
Contributors: 邹景立