Yii2表单验证场景切换后需手动validate()并返回JSON错误:先设$model->scenario,再调用validate(),用getErrors()获取错误数组,最后以JSON格式响应。

Yii2 表单验证场景(scenario)切换后,若想统一以 JSON 格式返回错误(比如用于 AJAX 提交),关键在于:**手动触发验证 + 捕获并格式化错误 + 统一响应出口**。默认情况下,`$model->validate()` 不会自动抛出异常,也不会自动转 JSON;而 `save()` 在失败时也只返回 false,需主动提取错误。
确保模型设置了正确的场景
在控制器中,必须显式设置 `scenario`,否则即使规则里定义了场景,模型仍使用默认场景(通常是 default):
- 在实例化后立即赋值:$model->scenario = 'login';
- 或在 new 时传入:$model = new User(['scenario' => 'login']);
- 检查模型类中是否正确定义了该场景的规则,例如:
public function rules()
{
return [
[['username', 'password'], 'required', 'on' => 'login'],
[['email'], 'email', 'on' => 'register'],
];
}
手动验证并捕获错误信息
不要依赖 `save()` 的返回值直接输出,而是先调用 `validate()`,再判断并构造 JSON 响应:
- 调用 $model->validate() 触发当前场景下的规则校验
- 用 $model->hasErrors() 判断是否有错
- 用 $model->getErrors() 获取多维数组形式的错误(键为属性名,值为字符串数组)
- 可选:用 yii\helpers\Json::encode() 或原生 json_encode() 输出,注意设置 header
控制器中返回 JSON 的典型写法
示例(Action 内):
$model = new LoginForm();
$model->scenario = 'login';
$model->load(Yii::$app->request->post(), '');
if (!$model->validate()) {
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return [
'success' => false,
'errors' => $model->getErrors(),
];
}
// 验证通过后处理登录逻辑...
进阶:全局统一错误响应(可选)
如项目中大量 AJAX 表单,可封装一个基类方法或行为(Behavior),在控制器中复用:
- 定义一个 renderJsonErrors($model) 工具方法
- 提取通用字段如 field、message,适配前端框架(如 Element UI 或 Ant Design 的表单错误格式)
- 对 `getErrors()` 结果做扁平化处理(例如转成 [ ['field'=>'username','message'=>'用户名不能为空'] ])











