验证规则写在 rules() 方法里,该方法返回二维数组驱动Yii模型验证,每项格式为[['属性名'], '验证器名', '参数'=>值],支持on/excel场景控制、targetClass跨表校验及public自定义方法。

验证规则写在哪?rules() 方法里,不是构造函数也不是行为
Yii 2.0.51 的模型验证逻辑全靠 rules() 方法返回的二维数组驱动。它不是配置文件,也不是注解,更不支持在 __construct() 里动态拼规则——改了也没用,框架只认这个方法的返回值。
- 每个子数组是一条验证规则,格式为
[['属性名'], '验证器名', '参数1' => '值1', ...] - 多个属性共用一条规则就写成
[['name', 'email'], 'required'],别拆成两条 - 自定义错误消息统一用
message键,比如'message' => '邮箱格式不对',别用errorMessage(那是旧版写法) - 如果某条规则只对特定场景生效,加
'on' => ['login'];想排除某些场景,用'except' => ['register']
required 和 safe 别混用:空字符串、null、0 的判定很实际
required 验证的是“有没有提交”,不是“是不是有效值”。它默认把空字符串 ''、null、0(数字零)都当“缺失”处理——但 0 是合法数值时这就出问题。
- 要允许
0通过required,加'requiredValue' => null,或者换用'filter'+'default'预处理 -
safe不是验证器,是白名单机制:没列在任何规则里的属性,默认被过滤掉(massive assignment时丢弃)。想保留未声明属性,得显式写[['extra_field'], 'safe'] - 别用
required检查“非空字符串”,它拦不住' '(纯空格),得配'trim' => true或单独加'string'规则
unique 验证器连表查重,不设 targetClass 就报错 Class not found
unique 默认在当前模型类里查,但如果模型没对应数据表(比如是表单模型 LoginForm),或要跨表校验(如检查邮箱是否已在 UserProfile 表存在),就必须指定 targetClass。
- 错误写法:
['email', 'unique']→ 报Class 'LoginForm' does not have a method named "findByEmail" - 正确写法:
['email', 'unique', 'targetClass' => '\app\models\User'] - 如果字段名不一致,比如
User表里叫user_email,得加'targetAttribute' => ['user_email' => 'email'] - 注意性能:没加数据库索引的字段走
unique,大表会慢,且事务中可能触发死锁
自定义验证方法必须是 public,且参数固定为 $attribute, $params
写 function validateAge($attribute, $params) 没问题,但写成 private、漏掉 $params、或加第三个参数,运行时直接静默跳过,不报错也不验证。
- 规则里引用写法:
['age', 'validateAge'],不用加$this->,也不用括号 -
$params是规则数组里除前两个之外的所有键值对,比如['age', 'validateAge', 'min' => 18],就能在方法里用$params['min'] - 手动触发错误用
$this->addError($attribute, '年龄不能小于18'),别用throw new Exception() - 如果验证逻辑依赖其他属性(比如确认密码),记得在规则里把两个属性都列上:
[['password', 'password_repeat'], 'validatePasswordMatch']
unique 的 targetClass 路径写错,和自定义方法签名不对——这两处不报语法错,但验证永远不生效。


















