Yii2中AJAX异步校验需服务端返回标准JSON格式错误信息:校验通过时返回{},失败时返回{"field":["error1","error2"]},HTTP状态码200且Content-Type为application/json。

Yii2 中使用 ActiveForm 实现 AJAX 异步校验,关键在于服务端正确响应校验失败的 JSON 格式,并让客户端能识别并显示错误。不需要整个表单提交,只需对单个字段(或多个字段)触发校验时返回结构清晰的错误信息。
服务端:独立返回校验错误的 JSON 响应
Yii2 的 ActiveForm 在 AJAX 校验(如失去焦点、输入时)会向控制器发起 POST 请求,URL 为 ?r=route/validate 形式(默认启用 enableAjaxValidation)。你需要在对应 action 中手动处理该请求,并只返回字段级错误,而非完整页面或重定向。
核心要求:返回 HTTP 状态码 200,Content-Type 为 application/json,JSON 结构必须是关联数组,键为属性名(模型属性),值为字符串数组(每个元素是一个错误提示)。
- 若校验通过:返回空数组
{}或{"name":[]} - 若校验失败:返回如
{"email":["邮箱格式不正确","该邮箱已被注册"]} - 务必调用
Yii::$app->response->format = Response::FORMAT_JSON(或直接用Json::encode()+exit)
示例控制器代码(SiteController.php):
use yii\web\Response;
use yii\helpers\Json;
public function actionValidate()
{
$model = new User();
if (Yii::$app->request->isPost) {
$model->load(Yii::$app->request->post());
// 只校验特定字段(如 email),避免全量校验开销
$errors = $model->validate(['email']) ? [] : $model->getErrors();
Yii::$app->response->format = Response::FORMAT_JSON;
return $errors;
}
throw new BadRequestHttpException('Invalid request');
}
视图中启用 ActiveForm AJAX 校验
确保表单开启 enableAjaxValidation,并指定验证触发的字段(可选):
<?php $form = ActiveForm::begin([
'id' => 'user-form',
'enableAjaxValidation' => true,
'enableClientValidation' => false, // 可关闭前端 JS 校验,完全交由后端
'validationUrl' => ['site/validate'], // 显式指定校验地址(推荐)
]); ?>
<?= $form->field($model, 'email')->textInput() ?>
<?php ActiveForm::end(); ?>
注意:validationUrl 必须与控制器中定义的 action 路径一致;若省略,默认会拼接当前路由 + /validate,容易出错。
避免常见陷阱
-
CSRF 验证拦截:AJAX 校验请求默认携带 CSRF token,但若你禁用了
enableClientValidation且未在请求头中传X-CSRF-Token,可能被拒绝。解决方案:在beforeSend中注入 token,或在 action 中临时关闭 CSRF(仅限校验 action):$this->enableCsrfValidation = false; -
模型加载失败:
$model->load()依赖formName(),若表单未设name或模型未定义场景,可能导致属性无法赋值。建议显式传入$model->load(Yii::$app->request->post(), '')或检查Yii::$app->request->post('User')结构 -
返回非标准 JSON:不要 echo 其他内容(如调试 var_dump)、不要包含 PHP 错误输出,否则 JSON 解析失败,浏览器控制台报错
Unexpected token < in JSON
进阶:自定义校验逻辑(不依赖模型规则)
有时需绕过模型规则,比如检查用户名是否含敏感词、调用第三方接口等。可在 actionValidate 中手动判断:
$email = Yii::$app->request->post('User')['email'] ?? '';
$errors = [];
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = ['邮箱格式不合法'];
} elseif (User::find()->where(['email' => $email])->exists()) {
$errors['email'] = ['该邮箱已被注册'];
}
return $errors;
只要最终返回的数组键名与表单字段名一致(如 email),ActiveForm 就能自动定位并显示错误。


















