yii2自定义参数验证有三种方式:一是模型内定义公共验证方法,如validatepasswordrepeat;二是创建继承validator的独立类,如mobilevalidator;三是使用闭包inline validator。

Yii2 中自定义规则验证请求参数,核心是通过继承 yii\validators\Validator 或使用闭包/匿名函数方式,在模型(Model)中定义校验逻辑。关键在于把业务校验逻辑封装成可复用、可配置、能返回明确错误信息的验证器。
在模型中定义自定义验证方法
最简单直接的方式:在 Model 类中写一个公共方法,然后在 rules() 中通过 ['attribute', 'methodName'] 调用。
- 方法名必须是 public,且接收两个参数:
$attribute(当前字段名)和$params(额外参数) - 校验失败时调用
$this->addError($attribute, $message) - 适合轻量、单模型专用的逻辑,比如“密码和确认密码一致”
示例:
public function rules()
{
return [
[['password', 'password_repeat'], 'required'],
['password_repeat', 'validatePasswordRepeat'],
];
}
public function validatePasswordRepeat($attribute, $params)
{
if ($this->password !== $this->password_repeat) {
$this->addError($attribute, '两次输入的密码不一致');
}
}
创建独立的自定义验证器类
适用于复杂、跨模型复用、需配置参数的场景。继承 yii\validators\Validator,重写 validateAttribute() 方法。
- 类可放在
@app/validators/目录下,记得配置自动加载或手动use - 支持在
rules()中传参,如['mobile', MobileValidator::class, 'country' => 'CN'] - 可在
init()中做初始化,校验逻辑集中在validateAttribute()
示例(手机号格式校验):
namespace app\validators;
use yii\validators\Validator;
class MobileValidator extends Validator
{
public $country = 'CN';
public function init()
{
parent::init();
if ($this->message === null) {
$this->message = '{attribute} 不是有效的手机号';
}
}
protected function validateAttribute($model, $attribute)
{
$value = $model->$attribute;
if (!is_string($value)) {
$this->addError($model, $attribute, $this->message);
return;
}
$pattern = $this->country === 'CN' ? '/^1[3-9]\d{9}$/' : '/^\+\d{1,3}\d{8,15}$/';
if (!preg_match($pattern, $value)) {
$this->addError($model, $attribute, $this->message);
}
}
}
使用 inline validator(闭包方式)
适合一次性、简单、无需复用的校验,写法紧凑,适合调试或原型阶段。
- 直接在
rules()中传匿名函数,函数签名同自定义方法 - 注意闭包内访问
$this需用use ($this)(PHP 7.4+ 支持),但更推荐用function ($model, $attribute)形式避免作用域问题
示例:
['status', function ($model, $attribute) {
if (!in_array($model->$attribute, [0, 1, 2])) {
$model->addError($attribute, '状态值只能是 0、1 或 2');
}
}]
配合场景(scenarios)和动态规则
实际项目中,不同接口或操作对同一字段要求不同。可通过 scenarios() 控制字段是否参与验证,并结合条件规则(when)动态启用校验。
- 定义场景:如
'create'和'update',在scenarios()中指定哪些属性必填/可选 - 用
when延迟判断是否执行某条规则,例如仅当 type=mobile 时才校验手机号格式 - 规则中可用
skipOnEmpty、skipOnError精细控制触发时机
示例:
['contact_value', MobileValidator::class, 'country' => 'CN',
'when' => function ($model) {
return $model->contact_type === 'mobile';
}]











