validate()静默失效主因是未先load()加载数据、场景未显式激活、skipOnEmpty/skipOnError默认跳过、或匿名函数未调addError()。

Yii2 的 validate() 看似调用就完事,但规则常静默失效——不是规则写错了,而是数据没进来、场景没激活、空值被跳过、或匿名函数没手动报错。
validate() 前没 load(),等于没校验
控制器里写 $model->validate() 却没错误?大概率是请求数据根本没进模型。Yii2 的 validate() 只校验当前属性值,不自动从 $_POST 或 JSON 体中取数。
- 必须先调
$model->load($request->post())(表单带前缀)或$model->load($request->getBodyParams(), '')(JSON 请求) -
load()默认按$model->formName()匹配键名;API 场景下传空字符串第二参数,否则字段全为空 - 验证失败后错误存在
$model->errors,不是抛异常,try/catch捕不到
自定义规则(匿名函数)不报错,是因为没调 addError
写成 ['price', function ($attr) { return $this->$attr > 0; }] 永远通过——Yii2 的 InlineValidator 不接收返回值,也不自动处理布尔结果。
- 必须显式调
$this->addError($attribute, '提示信息') - 正确写法:
['price', function ($attr) { if ($this->$attr addError($attr, '价格必须大于0'); }] - 该函数只在服务端生效,客户端无 JS 校验,需配合 ActiveForm 的 AJAX 验证才支持失焦触发
规则写了却“不执行”,可能是 skipOnEmpty 或 skipOnError 在作祟
比如字段为空、或前面某条规则已报错,后续规则(尤其是自定义方法)默认直接跳过——这是 Yii2 的默认行为,不是 bug。
- 想让规则始终运行,必须加
'skipOnEmpty' => false和'skipOnError' => false - 例如:
[['B'], 'requiredByASpecial', 'skipOnEmpty' => false, 'skipOnError' => false] - 注意:
skipOnEmpty控制空值是否跳过;skipOnError控制前面有错是否跳过本条
场景(scenario)设了但没生效,三处缺一不可
场景不是开关按钮,它需要模型类、规则声明、控制器三者联动才能起作用。
- 模型中必须定义
scenarios()方法,明确列出该场景包含哪些属性(不能只靠rules()推断) -
rules()中某条规则要生效于特定场景,得写'on' => 'xxx';没写on的规则才对所有场景生效 - 控制器里必须显式赋值:
$model->scenario = 'xxx';构造函数传参或配置项都不生效
最易忽略的其实是 load() 和 skipOnEmpty 的组合:数据没加载进去,规则再全也没用;空字段被跳过,自定义逻辑就永远不跑。这两个点卡住,$model->errors 就永远为空数组,连调试线索都断了。


















