PHP项目ThinkPHP验证器如何自定义

wen PHP项目 3

本文目录导读:

PHP项目ThinkPHP验证器如何自定义

  1. 创建自定义验证器
  2. 自定义验证规则
  3. 注册自定义验证器
  4. 使用场景验证
  5. 控制器中使用自定义验证器
  6. 验证器扩展技巧

在ThinkPHP框架中,自定义验证器是非常常见的需求,下面我来详细介绍如何自定义验证器。

创建自定义验证器

基础验证器类

<?php
namespace app\api\validate;
use think\Validate;
class UserValidate extends Validate
{
    // 验证规则
    protected $rule = [
        'username'  => 'require|max:20|unique:user',
        'email'     => 'require|email',
        'password'  => 'require|min:6|max:20',
        'phone'     => 'require|mobile',
    ];
    // 验证提示信息
    protected $message = [
        'username.require'  => '用户名不能为空',
        'username.max'      => '用户名长度不能超过20个字符',
        'username.unique'   => '用户名已存在',
        'email.require'     => '邮箱不能为空',
        'email.email'       => '邮箱格式不正确',
        'password.require'  => '密码不能为空',
        'password.min'      => '密码长度不能少于6位',
        'password.max'      => '密码长度不能超过20位',
        'phone.require'     => '手机号不能为空',
        'phone.mobile'      => '手机号格式不正确',
    ];
    // 场景设置
    protected $scene = [
        'register' => ['username', 'email', 'password'],
        'login'    => ['username' => 'require', 'password' => 'require'],
        'update'   => ['username', 'phone'],
    ];
}

自定义验证规则

在验证器类中添加自定义方法

<?php
namespace app\api\validate;
use think\Validate;
class CustomValidate extends Validate
{
    protected $rule = [
        'card_number' => 'require|checkCardNumber',
        'birthday'    => 'dateFormat:Y-m-d',
        'age'         => 'number|between:1,120',
    ];
    // 验证提示信息
    protected $message = [
        'card_number.require'     => '卡号不能为空',
        'card_number.checkCardNumber' => '卡号格式不正确',
        'birthday.dateFormat'     => '出生日期格式不正确',
        'age.number'              => '年龄必须是数字',
        'age.between'             => '年龄必须在1-120之间',
    ];
    // 自定义验证规则方法
    // 注意:方法名要以check开头
    protected function checkCardNumber($value, $rule, $data = [], $field = '')
    {
        // $value 为被验证的值
        // $rule 为规则参数(这里是空字符串)
        // $data 为当前验证的所有数据
        // $field 为字段名
        // 自定义验证逻辑
        if (!preg_match('/^[A-Za-z0-9]{10,20}$/', $value)) {
            return false;
        }
        return true;
    }
    // 另一个自定义验证方法示例
    protected function checkBirthDate($value, $rule, $data = [])
    {
        // 验证年龄是否大于18岁
        if (strtotime($value) > strtotime('-18 years')) {
            return '年龄必须大于18岁';
        }
        return true;
    }
}

使用静态方法定义验证规则

<?php
namespace app\api\validate;
use think\Validate;
class AdvanceValidate extends Validate
{
    protected $rule = [
        'name' => 'require|checkName',
        'info' => function($value, $data) {
            // 闭包函数验证
            if (empty($value['city']) || empty($value['address'])) {
                return '地址信息不完整';
            }
            return true;
        }
    ];
    // 或使用静态方法
    public function checkName($value, $rule, $data = [])
    {
        // 自定义规则
        if (strlen($value) < 2) {
            return '用户名长度至少2个字符';
        }
        return true;
    }
}

注册自定义验证器

在应用配置中注册(可选)

可以在 config/validate.php 中添加:

return [
    // 自定义验证器
    'extend' => [
        'card' => 'app\api\validate\CustomValidate::checkCardNumber',
    ],
];

直接实例化使用

<?php
namespace app\api\controller;
use app\api\validate\UserValidate;
use think\Request;
class User
{
    public function register(Request $request)
    {
        // 获取请求数据
        $data = $request->post();
        // 创建验证器实例
        $validate = new UserValidate();
        // 使用场景验证
        if (!$validate->scene('register')->check($data)) {
            // 获取错误信息
            return json([
                'code' => 0,
                'msg' => $validate->getError()
            ]);
        }
        // 验证通过,继续业务逻辑
        return json(['code' => 1, 'msg' => '验证通过']);
    }
    // 使用门面方式
    public function login(Request $request)
    {
        $data = $request->post();
        // 使用门面方式调用
        $validate = new UserValidate();
        $result = Validate::rule([
            'username' => 'require',
            'password' => 'require|min:6'
        ])->check($data);
        if (!$result) {
            return json(['code' => 0, 'msg' => '验证失败']);
        }
    }
}

使用场景验证

<?php
namespace app\api\validate;
use think\Validate;
class ArticleValidate extends Validate
{
    protected $rule = [
        'title'       => 'require|max:100',
        'content'     => 'require|min:10',
        'author'      => 'require|max:20',
        'category'    => 'require|number',
        'status'      => 'in:0,1',
        'start_time'  => 'date',
        'end_time'    => 'date|checkEndTime',
    ];
    protected $message = [
        'title.require'     => '标题不能为空',
        'title.max'         => '标题最多100个字符',
        'content.require'   => '内容不能为空',
        'content.min'       => '内容最少10个字符',
        'author.require'    => '作者不能为空',
        'category.require'  => '分类不能为空',
        'category.number'   => '分类格式不正确',
        'status.in'         => '状态设置不正确',
        'start_time.date'   => '开始时间格式不正确',
        'end_time.date'     => '结束时间格式不正确',
    ];
    // 场景定义
    protected $scene = [
        'add'     => ['title', 'content', 'author', 'category', 'status'],
        'edit'    => ['title', 'content', 'author', 'category'],
        'delete'  => ['id' => 'require|number'],
        'query'   => ['category', 'start_time', 'end_time', 'status'],
    ];
    // 自定义验证方法
    protected function checkEndTime($value, $rule, $data = [])
    {
        if (isset($data['start_time']) && $value < $data['start_time']) {
            return '结束时间不能早于开始时间';
        }
        return true;
    }
}

控制器中使用自定义验证器

<?php
namespace app\api\controller;
use app\api\validate\ArticleValidate;
class Article
{
    public function save()
    {
        $data = request()->post();
        // 方式一:使用场景
        $validate = new ArticleValidate();
        if (!$validate->scene('add')->check($data)) {
            return error($validate->getError());
        }
        // 方式二:使用自动验证
        $validate = new ArticleValidate();
        if (!$validate->check($data)) {
            return error($validate->getError());
        }
        // 方式三:直接验证指定字段
        $validate = new ArticleValidate();
        if (!$validate->batch(true)->check($data)) {
            // batch(true) 一次性返回所有错误信息
            return error(['errors' => $validate->getError()]);
        }
        // 验证通过,处理业务
        return success();
    }
}

验证器扩展技巧

使用正则表达式

// 自定义手机号验证
protected function checkMobile($value)
{
    $pattern = '/^1[3-9]\d{9}$/';
    return preg_match($pattern, $value) ? true : false;
}
// 自定义身份证号验证
protected function checkIdCard($value)
{
    $pattern = '/^\d{17}[\dXx]$/';
    return preg_match($pattern, $value) ? true : false;
}

使用闭包验证

protected $rule = [
    'password' => [
        'require',
        'min' => 6,
        function($value) {
            // 复杂验证逻辑
            if (!preg_match('/[A-Z]/', $value)) {
                return '密码必须包含大写字母';
            }
            if (!preg_match('/[0-9]/', $value)) {
                return '密码必须包含数字';
            }
            return true;
        }
    ]
];

多语言支持

// 在 message 中使用占位符
protected $message = [
    'username.require' => '{username}不能为空',
];
// 动态设置提示信息
$validate->message([
    'username.require' => '用户名不能为空,这是动态设置',
]);

ThinkPHP验证器的自定义方法非常灵活,你可以:

  1. 在验证器类中定义规则和方法
  2. 使用场景控制不同情况下的验证规则
  3. 编写自定义验证方法实现特定业务逻辑
  4. 通过闭包或静态方法实现简单验证
  5. 返回布尔值或错误信息字符串

正确使用自定义验证器可以提高代码复用性,减少重复代码,使验证逻辑更加清晰和可维护。

抱歉,评论功能暂时关闭!