yii2条件校验需用when回调控制触发时机并设skiponempty=>false确保空值验证,复杂逻辑应使用内联验证器配合adderror()报错。

Yii2 中做条件校验,核心是让某条规则只在特定条件下触发,比如“当 status=1 时,reason 字段才必须填写”。这不是简单加个 required 就能解决的,得靠 when 和 skipOnEmpty 的配合,再结合验证逻辑本身控制。
用 when 控制规则是否执行
when 是一个回调函数,返回 true 才会真正运行这条规则。它接收模型实例和属性名两个参数,适合做跨字段判断:
- 写法示例:
['reason', 'required', 'when' => function ($model) { return $model->status === 1; }] - 注意:回调里不能直接用
$attribute,因为when不传这个参数;要判断的字段名是规则里声明的那个(这里是reason) - 支持闭包或数组形式:
'when' => [$this, 'shouldValidateReason'],对应方法需为public
空值处理要手动干预
默认情况下,required 规则遇到空值(null、空字符串)会直接跳过验证 —— 但你可能希望“status=1 且 reason 为空”时明确报错。这时得关掉自动跳过:
- 加上
'skipOnEmpty' => false,确保即使reason为空也走验证逻辑 - 完整写法:
['reason', 'required', 'when' => fn($m) => $m->status === 1, 'skipOnEmpty' => false] - 这样,当
status是 1 且reason为空时,required就会报“必填”错误
复杂逻辑直接写内联验证器
如果条件判断更复杂(比如多字段联动、数据库查询、正则匹配),就别硬套内置规则,改用内联验证器:
- 规则写成:
['reason', function ($model, $attribute, $params) { if ($model->status === 1 && empty($model->$attribute)) { $model->addError($attribute, '状态为1时,原因不能为空'); } }] - 务必检查空值:
if (empty($model->$attribute)) return;可加可不加,取决于你是否想跳过空值校验 - 错误必须用
$model->addError(),不能return false或抛异常
避免常见失效问题
条件规则“不生效”通常卡在这几个点:
-
when回调返回了false或没返回值(PHP 默认返回null,等价于false) - 忘了设
'skipOnEmpty' => false,导致空值被静默跳过 - 字段本身没赋值(比如表单没提交该字段),模型属性为
null,when判断时要注意用===而非== - 规则写在了错误的场景(
on参数)下,而当前模型scenario不匹配











