yii2中自定义验证器用于处理复杂业务校验,如用户名需含中文、英文、数字、下划线且长度2–16位;推荐继承yii\validators\validator并重写validateattribute方法。

在 Yii2 中,自定义验证器是处理复杂业务校验逻辑的常用方式,尤其适合对字符串参数(如手机号、邮箱别名、用户名格式、身份证号等)做非标准规则的验证。下面以「校验用户名是否只含中文、英文、数字和下划线,且长度 2–16 位」为例,给出完整可运行的自定义验证器实例。
定义独立验证器类
推荐将验证逻辑封装为独立类,继承 yii\validators\Validator,重写 validateAttribute 方法:
// components/UsernameValidator.php
<?php namespace app\components;
use yii\validators\Validator;
class UsernameValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
$value = $model->$attribute;
// 空值跳过(若需允许空,可加 $this->skipOnEmpty = true;)
if ($value === null || $value === '') {
return;
}
// 类型检查
if (!is_string($value)) {
$this->addError($model, $attribute, '用户名必须是字符串');
return;
}
// 长度 & 字符范围校验
if (strlen($value) 16) {
$this->addError($model, $attribute, '用户名长度必须在 2 到 16 个字符之间');
return;
}
// 只允许中文、英文字母、数字、下划线
if (!preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9_]+$/u', $value)) {
$this->addError($model, $attribute, '用户名只能包含中文、英文字母、数字和下划线');
}
}
}
在模型中使用该验证器
在 Model 的 rules() 方法中注册验证器,支持数组配置或对象实例两种写法:
// models/UserForm.php
<?php namespace app\models;
use yii\base\Model;
use app\components\UsernameValidator;
class UserForm extends Model
{
public $username;
public function rules()
{
return [
[['username'], 'required'],
[['username'], UsernameValidator::class], // 方式一:类名字符串
// [['username'], new UsernameValidator()], // 方式二:实例化(更灵活,可传构造参数)
// 其他内置规则可并存
[['username'], 'string', 'max' => 16],
];
}
}
支持传参的增强版写法(可选)
若需动态控制规则(如不同场景下长度上限不同),可在验证器构造函数中接收参数,并在 rules() 中传入:
// components/UsernameValidator.php(增强版)
class UsernameValidator extends Validator
{
public $minLength = 2;
public $maxLength = 16;
public function init()
{
parent::init();
if ($this->message === null) {
$this->message = '用户名格式不合法';
}
}
public function validateAttribute($model, $attribute)
{
$value = $model->$attribute;
if ($value === null || $value === '') {
return;
}
if (!is_string($value)) {
$this->addError($model, $attribute, '用户名必须是字符串');
return;
}
$len = mb_strlen($value, 'UTF-8');
if ($len minLength || $len > $this->maxLength) {
$this->addError($model, $attribute, "用户名长度必须在 {$this->minLength} 到 {$this->maxLength} 个字符之间");
return;
}
if (!preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9_]+$/u', $value)) {
$this->addError($model, $attribute, '用户名只能包含中文、英文字母、数字和下划线');
}
}
}
调用时传参:
[['username'], UsernameValidator::class, 'minLength' => 3, 'maxLength' => 20]
控制器中触发验证并返回结果
在 Controller 中调用 validate() 即可触发全部规则,包括自定义验证器:
public function actionRegister()
{
$model = new UserForm();
if ($model->load(\Yii::$app->request->post()) && $model->validate()) {
// 验证通过,执行注册逻辑
return $this->asJson(['success' => true]);
}
// 返回错误信息(含自定义验证器的提示)
return $this->asJson([
'success' => false,
'errors' => $model->getErrors()
]);
}
前端收到的 errors 格式示例:
{"username": ["用户名只能包含中文、英文字母、数字和下划线"]}
注意:自定义验证器默认不参与客户端验证(JS),如需前端同步提示,需额外配置 clientValidate 方法并注册 JS 规则;一般简单字符串校验建议服务端为主,兼顾安全与维护性。











