升级后save()不触发验证,主因是模型rules()未完整声明字段的safe属性或验证规则,或调用时传入false参数跳过验证,需检查rules()、scenarios()、save()调用方式及behavior干扰。

升级后 save() 不触发验证,大概率是模型验证逻辑被绕过或配置未同步更新,不是框架突然失效,而是新版本对验证流程更严格或行为有细微调整。
检查 rules() 是否完整且场景匹配
Yii2.0.50 对 safe 属性的控制更明确。如果字段没在 rules() 中声明为 'safe' 或对应验证规则(如 'string'、'required'),即使赋值成功,save() 也会静默过滤该字段,验证自然不跑。
- 确认新增或修改的字段是否已加入
rules(),例如:['status', 'safe']或['status', 'in', 'range' => [0,1]] - 若用了自定义
scenario(比如'update'),检查scenarios()方法中是否把该字段列入对应场景的safeAttributes() - 临时加一行调试:
var_dump($model->activeAttributes());,看当前场景下哪些字段被认定为可操作属性
确认 save() 调用方式是否跳过了验证
save() 默认会先调用 validate(),但某些写法会绕过它:
- 显式传参
$model->save(false)→ 完全跳过验证,只执行 SQL - 直接调用
$model->update()或$model->updateAll()→ 不触发beforeValidate/afterValidate,也不走rules() - 用
$model->attributes = $data批量赋值后调用save()→ 若字段不在safe列表里,仍会被丢弃,验证也不会覆盖它
验证是否真被调用?加断点或日志确认
别只看返回值,要验证“验证过程是否发生”:
- 在模型中重写
beforeValidate(),加file_put_contents('/tmp/debug.log', "beforeValidate called\n", FILE_APPEND);,看日志有没有输出 - 手动调用
$model->validate(),再查$model->hasErrors()和$model->getErrors(),确认验证器是否生效 - 注意:如果
scenarios()返回空数组或未覆盖父类逻辑,可能导致所有字段都被视为非 safe,验证直接跳过
检查是否有行为(Behavior)或事件干扰
某些 Behavior(如时间戳自动填充、软删除)可能在 beforeSave 中修改了属性,或提前中断了流程;升级后部分 Behavior 的默认行为可能变化:
- 查看模型是否挂载了自定义 Behavior,尤其是重写了
events()或在beforeSave中返回false - 检查是否误将
beforeValidate事件绑定到某个不生效的实例上(比如在静态方法中注册) - 运行
var_dump($model->behaviors());确认实际加载了哪些行为











