When we need to pass the validator validate to uniquely check the fields in the database, we can use the unique rule to achieve, but tp is not very detailed description and examples.

At the same time unique the validator needs to verify the uniqueness of the data outside 除当前活动记录 , it does not do the relevant encapsulation, and can only hard-write the rules at the business level, which is not elegant. The so-called validation rules should be in the validator.

Here are some scenes from my daily development to sort out for you:

unique Syntax rules

 // modelClassName 你需要关联校验的模型类名(直接写表名会比较硬编码)
// col1^col2 参与唯一校验的字段
// [
//   ['col1', '=', $formData['col1']],
//   ['col2', '=', $formData['col2']],
// ]
// $pkId 「编辑」场景防自杀
// [['id', '<>', $pkId]]

protectd $rule = [
    "colName" => "require|unique:modelClassName,col1[^col2][,$pkId]"
]

// 给出具体规则所组装出的唯一性查询语句
// "require|unique:User,name^deleted"
$exists = $query->where([
  'name' => $formData['name'],
  'deleted' => $formData['deleted']
])->find();

// "require|unique:User,name^deleted, 1"
$exists = $query->where([
  'name' => $formData['name'],
  'deleted' => $formData['deleted']
])->where([['id', '<>', 1]])->find();

模型

 /**
 * @property int $id
 * @property string $name 唯一
 * @property int $age
 * @property int $deleted 软删除
class User extends Model
{
    protected $connection = "db_app";//多库链接配置
}

验证器基类-优化ed

According to whether there is ---0a731fafea3a2d30437baa3102525ecb 表单数据 in pkId to dynamically generate the verification rules of unique

 <?php

namespace app\common\validate;

use think\Validate;

/**
 * Class MaterialTypeValidate
 *
 * @package app\prt\validate
 * @see     \think\Validate::unique 解析器
 */
class BaseValidate extends Validate
{
    /**
     * 根据表单数据动态挂载 pkId
     * 编辑时的 unique 校验 应使用 pkId 来忽略当前行
     * 同时如果有软删除 那么还要加入 deleted=0 的条件来限制只校验有效记录
     * formData ['col1' => xxx, 'col2' => xxx, 'deleted'=>0]
     * unique|modelName,col1^col2^deleted,pkId
     * unique多字段校验时验证器会检查表单数据有对应的字段,存在才会加入条件
     * 为了忽略软删除要让表单数据中的 deleted=0 显示定义,排除已删除的数据
     * BaseValidate constructor.
     *
     * @param int   $pkId
     * @param array $rules
     * @param array $message
     * @param array $field
     */
    public function __construct($pkId = 0, array $rules = [], array $message = [], array $field = [])
    {
        parent::__construct($rules, $message, $field);
        // 有 id 则为编辑,追加pkId条件
        // 无 id 则为新增,全局唯一检查
        array_walk($this->rule, function (&$row) use ($pkId) {
            $row = str_replace(",{pkId}", "," . $pkId ?? "", $row);
        }, $this->rule);
    }
}

The field uniqueness of ---8a6a88ded801671aa610b1d864199d92 全局有效记录 needs to be verified when adding, and the field uniqueness of 编辑 needs to be verified when 除当前记录外 .

 <?php

namespace app\http\validate;

use app\common\validate\BaseValidate;
use app\http\model\User;

/**
 * Class UserValidate
 *
 * @package app\http\validate
 */
class UserValidate extends BaseValidate
{
    protected $rule = [
        'id'     => 'require|number',
        'name'   => 'require|unique:' . User::class . ',name^deleted,{pkId}',
        'age' => 'require|number',
    ];

    protected $message = [
        'id.require'   => 'id无效',
        'id.number'    => 'id无效',
        'name.require' => '姓名必须',
        'name.unique'  => '姓名重复',
        'age.require'  => '年龄必须',
        'age.number'   => '年龄无效',
    ];
    
    protected $scene = [
        'add'  => ['name', 'age'],
        'edit' => ['id', 'name', 'age'],
    ];
}

实例

 public function save($userData)
{
    // 根据有无 id 来动态渲染 unique 条件的校验范围
    $validate = new UserValidate($userData['id'] ?? 0);
    
    // 只校验未删除的有效数据
    if (User::hasSoftDelete()) {
        $userData['deleted'] = 0;
    }

    if (empty($userData['id'])) {
        $validateRes = $validate->scene('add')->check($userData);
    } else {
        $validateRes = $validate->scene('edit')->check($userData);
    }
    
    if (!$validateRes) {
        throw new Exception($validate->getError());
    }
}

Parser for unique

 \think\Validate::unique

big_cat
1.7k 声望130 粉丝

规范至上


引用和评论

0 条评论