本文目录导读:

在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验证器的自定义方法非常灵活,你可以:
- 在验证器类中定义规则和方法
- 使用场景控制不同情况下的验证规则
- 编写自定义验证方法实现特定业务逻辑
- 通过闭包或静态方法实现简单验证
- 返回布尔值或错误信息字符串
正确使用自定义验证器可以提高代码复用性,减少重复代码,使验证逻辑更加清晰和可维护。