自定义验证器不读取参数的根源在于rules()中未显式传参或验证器未正确定义属性并调用parent::init();需确保参数以键值对形式写入规则数组,且验证器类中声明public属性并在init()中调用parent::init()。

自定义验证器不读取参数,通常不是验证器本身写错了,而是参数传递方式或验证器初始化环节出了问题。核心在于:Yii2 验证器的参数必须通过 规则数组中显式传入,且验证器类需正确定义对应属性并完成初始化。
检查 rules() 中是否正确传参
在模型的 rules() 方法里,参数必须以键值对形式直接写在规则项中,不能靠构造函数或外部赋值:
- ✅ 正确写法(参数作为数组元素传入):
[['mobile'], 'app\validators\MobileValidator', 'countryCode' => '86', 'strict' => true], - ❌ 错误写法(只写类名、没传参,或参数写在错误位置):
[['mobile'], 'app\validators\MobileValidator'], // 参数全丢失
[['mobile'], MobileValidator::class, 'countryCode' => '86'], // 类名未加引号,PHP 解析报错
确认验证器类中已声明并初始化参数属性
所有要接收的参数,必须在验证器类中声明为 public 属性,并在 init() 中调用 parent::init(),否则参数不会被自动注入:
- 必须有:
public $countryCode = '86';
public $strict = false; - 必须重写
init()并调用父类:
public function init()
{
parent::init(); // 关键!否则 $this->countryCode 始终为空
}
避免混淆 skipOnEmpty 和自定义参数
像 'skipOnEmpty' => false 这类是 Yii2 验证器基类的内置行为控制属性,不是你的业务参数。它们和你自定义的 countryCode 是同一层级的键,但作用不同:
- 两者可共存:
[['mobile'], MobileValidator::class, 'countryCode' => '86', 'skipOnEmpty' => false], - 若漏掉
skipOnEmpty的赋值,它会使用默认值(true),导致空值时整个验证被跳过——你以为“参数没生效”,其实是验证根本没运行。
调试小技巧:打印参数值确认是否到达
在验证器的 validateAttribute() 开头临时加一行:
- var_dump($this->countryCode, $this->strict); die();
- 如果输出为
null或false,说明参数根本没传进来,立刻回头检查rules()写法和属性声明;
如果输出正常,问题就在验证逻辑内部。

















