内联验证器适用于简单一次性校验,需用匿名函数或数组回调定义,签名必须为function($model, $attribute, $params),失败时调用addError();独立验证类适合复用复杂校验,须继承Validator、重写validateAttribute(),类名以Validator结尾。

内联验证器:适合简单、一次性校验
直接在 rules() 方法里用匿名函数或数组回调定义,不需额外类文件。适用于字段间逻辑判断,比如密码与确认密码是否一致。
- 签名必须是 function($model, $attribute, $params),三个参数缺一不可
- 失败时调用 $model->addError($attribute, $message),不能 return false 或 throw 异常
- 写法只能是 ['password_repeat', function (...) {...}] 或 ['password_repeat', [$this, 'checkPasswordMatch']],不能只写字符串
'checkPasswordMatch' - 若字段允许为空(如没加 required 规则),内联验证默认仍会执行;如需跳过空值,需手动判断:
if (empty($model->$attribute)) return;
独立验证类:适合复用、复杂或带配置的校验
新建 PHP 类继承 yii\validators\Validator,重写 validateAttribute() 方法。适合手机号、身份证、自定义格式等通用校验逻辑。
- 类名必须以 Validator 结尾(如
PhoneValidator),否则自动加载失败 - 务必在 init() 中调用 parent::init(),否则
$this->message等属性未初始化 - 参数通过 public 属性声明(如
public $strict = true;),并在 rules 中传入:['mobile', 'PhoneValidator', 'strict' => false] - 支持客户端验证需实现 clientValidateAttribute(),返回合法 JS 字符串(注意引号转义)
when 与 skipOnEmpty 的配合逻辑
二者共同控制验证是否触发,但优先级和语义不同:
-
when 是前置开关:返回 false 则整条规则不执行,
skipOnEmpty不再起作用 -
skipOnEmpty 默认为 true,仅当
when返回 true 后才生效:若属性为空且skipOnEmpty === true,则跳过验证 - 常见组合:
'when' => fn($m) => $m->status === 1+'skipOnEmpty' => false,确保状态为 1 时即使为空也校验
常见易错点与避坑提示
实际开发中高频出错的地方,建议写完立刻检查:
- 验证方法名写错或未声明为 public,导致调用失败且无报错
- 忘记在
addError()中传入正确属性名(如写成$this->addError('username', ...)却校验的是email字段) - each 嵌套 rule 时,子规则语法写成
['integer', 'min' => 1]而非['integer', 'min' => 1]—— 实际写法正确,但容易漏掉 key-value 对应关系 - exist 验证中
targetAttribute没配对,导致查错字段(例如表单字段是senderId,但 user 表主键是id,须显式写'targetAttribute' => ['senderId' => 'id'])


















