validate()没效果是因为未先调用load()加载请求数据;场景需同时定义scenarios()、在rules()中指定on、并手动设置model->scenario;save()会操作数据库而validate()仅校验。

控制器里直接调用 validate() 为什么没效果?
因为 validate() 不会自动赋值,只校验当前模型属性的值——而你很可能还没把请求数据塞进去。常见错误是写了 $model->validate() 就以为完事了,结果 $model->hasErrors() 始终返回 false,但实际提交的数据根本没进模型。
- 必须先调用
load()(或手动赋值),再validate() -
load()默认按formName()匹配 POST 键名,如果表单没加前缀或用了 JSON,得传空字符串:$model->load($request->getBodyParams(), '') - 验证失败时,错误存在
$model->errors,不是抛异常,别指望try/catch捕获
场景(scenario)设了但没生效?检查这三处
场景不是“设了就跑”,它依赖属性定义、规则声明和主动激活三个环节。漏掉任意一个,scenario 就形同虚设。
- 模型类里必须显式定义
scenarios()方法,不能只写rules();默认的'default'场景不会自动包含所有属性 -
rules()中某条规则若指定了['on' => 'xxx'],那它只在该场景下触发;没写on的规则,才对所有场景生效 - 控制器中必须显式设置:
$model->scenario = 'xxx',不能靠构造函数参数或配置自动切换
validate() 和 save() 的区别到底在哪?
save(false) 跳过验证,save(true)(默认)会先调 validate() 再存库——但二者行为不等价。关键差异在数据来源和副作用。
-
validate()只校验当前模型属性值,不碰数据库;save()会尝试 INSERT/UPDATE,失败时可能已触发事务或外键约束 -
save()成功后会自动更新主键、时间戳等属性;validate()完全无副作用 - 批量操作(如导入)建议先
validate()集中收集错误,再统一save(),避免部分成功部分失败导致状态不一致
JSON 请求体下验证总失败?注意 load() 的第二个参数
Yii2 默认从 $_POST 或 $_GET 读取,但 API 请求多为 application/json,load() 默认找不到数据源。
- 先用
$request->getRawBody()解析 JSON:$data = Json::decode($request->getRawBody()) - 再手动赋值:
$model->setAttributes($data, false)(false表示跳过安全过滤) - 或者改用
load()第二个参数指定空字符串:$model->load($data, ''),绕过 formName 匹配逻辑 - 注意:此时
rules()中的'safe'属性限制失效,所有字段都可被赋值,务必确认字段白名单











