yii2异步表单提交核心是前端ajax提交、后端返回标准json响应(含errors或success)、前端按约定渲染错误;需配置模型规则、控制器判断ajax并返回验证结果、视图禁用默认验证并用jquery处理提交与错误高亮,确保input id与错误字段键严格匹配。

Yii2 中实现异步表单提交并支持服务端 JSON 验证,核心在于:前端用 AJAX 提交、后端返回标准 JSON 响应(含验证错误)、前端按约定渲染错误。下面是一套可直接运行的实战代码,覆盖控制器、视图、模型和 JS 处理逻辑。
1. 模型定义:启用场景 + 定义验证规则
确保模型支持 AJAX 验证所需的字段和规则,推荐使用 scenario 区分普通提交与异步提交(如需不同验证逻辑):
// models/ContactForm.php
namespace app\models;
use yii\base\Model;
class ContactForm extends Model
{
public $name;
public $email;
public $message;
public function rules()
{
return [
[['name', 'email', 'message'], 'required'],
['email', 'email'],
['message', 'string', 'max' => 500],
];
}
public function attributeLabels()
{
return [
'name' => '姓名',
'email' => '邮箱',
'message' => '留言',
];
}
}
2. 控制器:接收 AJAX 请求,返回 JSON 响应
控制器动作需判断是否为 AJAX 请求,验证失败时返回含 errors 的 JSON;成功时返回 success 标识及可选数据:
// controllers/SiteController.php
use app\models\ContactForm;
use yii\helpers\Json;
use yii\web\Response;
public function actionAjaxContact()
{
\Yii::$app->response->format = Response::FORMAT_JSON;
$model = new ContactForm();
if ($model->load(\Yii::$app->request->post()) && $model->validate()) {
// ✅ 验证通过,可执行保存等逻辑
// $model->save(); // 示例:存入数据库
return ['success' => true, 'message' => '提交成功!'];
}
// ❌ 验证失败:返回 errors 数组,结构为 ['field' => ['error msg 1', 'error msg 2']]
$errors = [];
foreach ($model->getErrors() as $attribute => $msgs) {
$errors[\yii\helpers\Html::getInputId($model, $attribute)] = $msgs;
// 或用 $attribute 直接作 key(需前端配合)
}
return [
'success' => false,
'errors' => $errors,
];
}
3. 视图:表单 + jQuery AJAX 提交 + 错误渲染
使用 Yii2 的 ActiveForm 生成表单,并禁用默认提交;用 jQuery 统一处理提交、校验反馈和错误高亮:
// views/site/ajax-contact.php
use yii\widgets\ActiveForm;
use yii\helpers\Html;
$model = new app\models\ContactForm();
$form = ActiveForm::begin([
'id' => 'contact-form',
'enableClientValidation' => false, // 关闭客户端验证,交由服务端统一处理
'enableAjaxValidation' => false, // 关闭 Yii 内置 AJAX 验证(我们手动控制)
'options' => ['enctype' => 'multipart/form-data'],
]);
echo $form->field($model, 'name')->textInput(['placeholder' => '请输入姓名']);
echo $form->field($model, 'email')->textInput(['placeholder' => '请输入邮箱']);
echo $form->field($model, 'message')->textarea(['rows' => 4, 'placeholder' => '请输入留言']);
echo Html::submitButton('提交', ['class' => 'btn btn-primary', 'id' => 'submit-btn']);
ActiveForm::end();
// 页面底部或单独 JS 文件
$('#contact-form').on('submit', function (e) {
e.preventDefault();
const $form = $(this);
const $btn = $('#submit-btn');
const formData = $form.serialize();
$btn.prop('disabled', true).text('提交中…');
$.post($form.attr('action') || '', formData)
.done(function (res) {
if (res.success) {
alert(res.message || '操作成功');
$form[0].reset(); // 重置表单
} else if (res.errors) {
// 清除旧错误
$form.find('.has-error').removeClass('has-error');
$form.find('.help-block').remove();
// 插入新错误
$.each(res.errors, function (inputId, messages) {
const $input = $('[id="' + inputId + '"]');
const $field = $input.closest('.form-group');
$field.addClass('has-error');
// 追加错误提示块(兼容 Yii2 默认样式)
const $helpBlock = $('<div class="help-block"></div>');
$.each(messages, function (_, msg) {
$helpBlock.append($('<p></p>').text(msg));
});
$field.append($helpBlock);
});
}
})
.fail(function () {
alert('网络错误,请重试');
})
.always(function () {
$btn.prop('disabled', false).text('提交');
});
});
4. 路由配置(确保可访问)
在 config/web.php 的 urlManager 中确认已开启美化 URL,或直接通过 index.php?r=site/ajax-contact 访问。若使用 RESTful 风格,也可配规则:
'rules' => [
'POST site/ajax-contact' => 'site/ajax-contact',
],
不复杂但容易忽略:确保控制器返回 Response::FORMAT_JSON,前端用 $.post(自动识别 JSON),错误字段 ID 与 Yii2 生成的 input ID 严格一致(如 ContactForm[name] → ID 是 contactform-name),否则无法精准定位错误位置。











