rules() 必须在模型类中定义为public方法并返回指定格式的二维数组,且需确保字段被load()加载、场景匹配、validate()被显式调用,任一环节缺失都会导致验证静默失效。

rules() 写错位置或格式导致验证完全不触发
验证规则只在模型类的 rules() 方法里返回的二维数组中生效,写在 init()、beforeValidate() 或行为里,框架根本不会读取。常见错误是把规则当普通逻辑写进构造函数,结果 validate() 始终静默通过。
-
rules()必须是 public 方法,且必须 return 一个数组,每项是 [属性名, 验证器名, 参数] 三元组,例如[['username'], 'required'] - 验证器名拼错(如写成
'require'而非'required')或键名写错(如用'onScenario'代替'on'),不会报错,但该条规则直接被忽略 - 字段名不在模型的
safe列表里(即没出现在scenarios()对应场景的字段白名单中),即使规则写了,load()也不会赋值,后续validate()就像在验空数据
save() 时 rules 不起作用,其实是 load() 根本没成功
ActiveRecord::save() 内部会调用 validate(),但它不会自动从请求中加载数据——你得先手动 $model->load($data)。很多人跳过这步,直接 new User(); $model->name = 'xxx'; $model->save(),看似能存,实则绕过了所有 rules() 校验(因为没走验证流程)。
- POST 表单字段带 model 前缀(如
user[username]),必须用$model->load(Yii::$app->request->post());若前端发的是扁平结构(如{"username":"a"}),得传空字符串:$model->load($data, '') - JSON 请求体默认不解析,
$_POST和getBodyParams()都为空,必须先$raw = Yii::$app->request->getRawBody()→$data = \yii\helpers\Json::decode($raw)→$model->load($data, '') -
load()返回布尔值,必须检查它是否为 true;返回 false 却继续validate(),等于拿一堆 null 属性去校验,结果永远“通过”
场景(scenario)设了但 rules 还是不生效
场景不是开关,而是过滤器:它只决定哪些字段被加载、哪些规则被启用。三处必须同时对齐,缺一不可。
- 模型中重写
scenarios(),明确返回字段白名单,例如return ['create' => ['name', 'email']];不写这个方法,scenario = 'create'后连name都不会被load()赋值 -
rules()里某条规则若写了'on' => 'create',就必须出现在上述scenarios()的'create'字段列表中,否则字段压根进不来,规则自然不跑 - 控制器中必须在
load()之后、validate()之前设$model->scenario = 'create';在构造时传参(new User(['scenario' => 'create']))可行,但在findOne()后设就无效——AR 实例的scenarios()默认只返回['default' => [...]],需手动重写
动态添加规则(addRule)后 validate() 仍不触发
addRule() 是实例级操作,添加的规则只属于当前对象,且生命周期极短。它不修改类定义,也不影响其他实例。
-
addRule()必须配合on参数和显式$model->scenario设置,例如$model->addRule('price', 'required', ['on' => 'vip'])+$model->scenario = 'vip' - 从数据库查出的 AR 实例(如
User::findOne(123))默认validators属性为空,addRule()才能真正挂上;但若你先load()再addRule(),要注意load()不会清空已有 validators,可能造成规则叠加或冲突 - 不要在
beforeValidate()里反复addRule(),没有去重机制,同一请求内多次验证会导致重复添加;更稳妥的是在init()或控制器 new 模型后一次性添加
最常被忽略的点是:rules 生效的前提不是“写了”,而是“字段被加载 + 场景匹配 + 规则未被过滤 + validate() 真正执行”。任何一环断开,验证就变成摆设,而框架几乎不报错。











