yii2中模型验证场景用于不同业务流程启用不同字段和规则;需重写scenarios()显式定义各场景属性,rules()中用on指定场景规则,控制器中必须提前设置scenario,且validate前须先调用load()加载数据。

在Yii2中设置模型验证场景,是为了让同一模型在不同业务流程(如创建、更新、登录)中启用不同的字段和验证规则。不设场景时所有规则全量生效,容易导致更新操作因缺失图片字段而失败,或登录时被强制要求填邮箱。
定义可用场景列表
在模型类(如app/models/News.php)中重写scenarios()方法,明确声明每个场景下允许操作的属性集合。
返回一个关联数组,键为场景名(如create、update),值为该场景下“活跃”的属性名数组。
【必须显式定义,不能只靠rules()中的on参数自动推导】
例如:
public function scenarios()<br>{<br> return [<br> 'create' => ['title', 'description', 'picture'],<br> 'update' => ['title', 'description', 'status'],<br> 'default' => ['title', 'description'],<br> ];<br>}
在验证规则中绑定场景
修改模型的rules()方法,在需要按场景触发的规则中添加'on'选项。
没写on的规则,默认对所有场景生效;写了on的,只在指定场景下校验。
比如图片只在创建时必填:
[['picture'], 'required', 'on' => 'create'],
而标题和描述在两个场景都必填:
[['title', 'description'], 'required', 'on' => ['create', 'update']],
注意:如果某字段不在当前场景的scenarios()列表里,即使规则写了on,load()也不会给它赋值——这一步是安全过滤,不是验证跳过。
控制器中激活指定场景
有三种方式任选其一,必须在调用load()或validate()前完成场景设置。
方法一:实例化后赋值
$model = new News();<br>$model->scenario = 'create';
方法二:构造时传参
$model = new News(['scenario' => 'update']);
方法三:在控制器动作开头统一设置(适合复用逻辑)
这一步漏掉,整个场景机制就失效——rules()里的on条件会全部被忽略,退化为default场景运行。
验证前必须先加载数据
第一步:调用load()把请求参数塞进模型。
默认按模型的formName()匹配POST键名,表单无前缀时可传空字符串:$model->load($request->post(), '')。
第二步:再执行validate()。
【validate()不会自动加载数据,只校验已有属性值——没load就validate,永远返回true】
验证失败后,错误信息存在$model->errors中,不是抛异常,别用try/catch捕获。











