yii2表单验证返回json响应的核心是控制器在验证失败时不跳转、不渲染页面,而是统一输出含错误字段和提示的结构化json数据,前端可直接解析展示;关键需禁用默认重定向、手动触发验证、规范响应格式。

Yii2 表单验证返回 JSON 响应,核心是让控制器在验证失败时不跳转、不渲染页面,而是统一输出结构化的 JSON 数据(含错误字段和提示),前端可直接解析并展示。关键点在于禁用默认重定向行为、手动触发验证、规范响应格式。
禁用表单提交的默认重定向
Yii2 的 ActiveForm 默认提交会刷新页面。要走 AJAX 路由,需显式设置:
- 视图中使用
ActiveForm::begin(['enableAjaxValidation' => true]) - 或手动配置:
['options' => ['data-pjax' => 1]]配合 Pjax,但更推荐原生 AJAX 验证 - 确保对应 action 不被 CSRF 验证拦截(AJAX 请求需携带
X-CSRF-Token头,或在控制器中临时关闭:$this->enableCsrfValidation = false;—— 生产环境建议保留并正确传 token)
在 Controller 中手动执行验证并返回 JSON
典型写法如下(以 SiteController::actionSignup() 为例):
public function actionSignup()
{
$model = new SignupForm();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if ($model->load(Yii::$app->request->post()) && $model->signup()) {
return $this->goHome();
}
return $this->render('signup', ['model' => $model]);
}
说明:
-
ActiveForm::validate($model)是 Yii2 内置方法,自动返回符合前端验证要求的 JSON 格式(如:{"username":["用户名已存在"],"email":["邮箱格式不正确"]}) - 必须加
isAjax判断,避免非 AJAX 请求也走此逻辑 - 无需手动调用
$model->validate(),ActiveForm::validate()内部已处理
自定义 JSON 响应结构(非 ActiveForm 场景)
若不用 ActiveForm(比如纯 API 接口或 Vue/React 前端),可完全自定义响应:
public function actionApiValidate()
{
$model = new ApiForm();
$post = Yii::$app->request->post();
if ($model->load($post) && $model->validate()) {
return ['success' => true, 'data' => $model->attributes];
} else {
$errors = [];
foreach ($model->getErrors() as $attribute => $msgs) {
$errors[$attribute] = implode(';', $msgs);
}
return [
'success' => false,
'errors' => $errors
];
}
}
注意:
- 确保该 action 的 response format 设为 JSON:
Yii::$app->response->format = Response::FORMAT_JSON;(或在配置中全局设置) - 错误信息可按需扁平化(如合并所有错误到
message字段)或保留字段级结构 - 生产环境建议统一封装响应类(如
JsonResponse::success()/::error())保持风格一致
前端接收与处理示例(jQuery)
ActiveForm 启用 enableAjaxValidation 后,框架自动绑定 beforeValidate 和 afterValidate 事件。如需手动控制:
$('#signup-form').on('beforeValidate', function (e, messages) {
// 可在此拦截、补充校验逻辑
});
$('#signup-form').on('afterValidate', function (e, messages) {
if ($.isEmptyObject(messages)) {
// 全局通过,可提交
console.log('验证通过');
}
});
若手写 AJAX:
- 监听表单 submit,
e.preventDefault() - 用
$.post()提交数据到验证接口 - 根据返回的
success字段判断,errors对象逐个注入到对应 input 的help-block或 tooltip 中











