Yii2表单提交失败不显示错误,通常因错误未渲染到视图:需确认$model->getErrors()有数据、使用ActiveForm::field()自动挂载、确保模型实例一致且模板含{error},或手写表单时在render前调用validate()并手动输出错误。

Yii2 表单提交失败后不显示错误信息,通常不是模型没验证,而是错误没“落”到视图里——$model->getErrors() 有数据,但你没读、没渲染、或者没在正确时机渲染。
表单提交后错误不显示,先确认 $model->getErrors() 是否真有内容
很多人卡在这一步:以为模型验证失败了,其实根本没进验证逻辑,或者验证通过了但业务逻辑抛了异常。在控制器 action 末尾加一句:
var_dump($model->getErrors()); die;
如果输出是空数组 [],说明:
- 模型没调用 $model->validate()(比如漏了 if ($model->load(Yii::$app->request->post()) && $model->validate()))
- 或者 POST 数据根本没进到 load()(常见于 CSRF 验证失败导致请求被拦截在中间件,连控制器都没进)
- 或者规则里用了 on 场景但没传 scenario
用 ActiveForm 小部件时,错误不自动显示?检查是否漏了 $form->field()
ActiveForm 的错误提示是靠 $form->field($model, 'name') 这个链式调用自动挂载的。如果你手动写了 <input name="User[name]">,哪怕模型有错误,也不会显示——ActiveForm 不会扫描原始 HTML。
必须用以下结构才能触发自动错误渲染:
<?php $form = ActiveForm::begin(); ?><br><?= $form->field($model, 'name')->textInput() ?><br><?= $form->field($model, 'email')->textInput() ?><br><?= Html::submitButton('Submit') ?><br><?php ActiveForm::end(); ?>注意:
- $model 必须是同一个实例(不能 new 一个新对象再传给视图)
- textInput() 后面不能跟 ->label(false) 之类强行删掉 wrapper 的操作,否则错误容器也被干掉了
- 如果用了自定义模板,确保模板里包含 {error} 占位符
手写表单 + 手动输出错误,要保证变量在渲染前已赋值
手写 HTML 表单时,错误信息得你自己 echo,但顺序错了就白忙:
- 验证逻辑(
$model->validate())必须在render()视图之前执行 - 错误变量如
$nameErr = $model->getFirstError('name');要在<input>标签之前计算好 - 每个字段下方紧挨着放错误提示,例如:
<input name="User[name]" value="<?= Html::encode($model->name) ?>"><br><? if ($nameErr): ?><br><div class="error"><?= $nameErr ?></div><br><? endif; ?>
别把整个表单包在 if ($model->hasErrors()) { ... } 里——那样验证失败才显示表单,用户根本看不到初始页面;应该始终显示表单,只条件渲染错误提示。
CSRF 失败导致 400 却没错误提示?那根本不是“表单验证错误”
出现 Unable to verify your data submission 或 Bad Request (#400),页面直接中断,$model->getErrors() 压根不会被执行——请求在到达控制器前就被 yii\web\Controller::beforeAction() 拦截了。
这时你看到的不是“验证失败”,而是“请求被拒绝”。排查重点是:
- 表单中是否缺失
<input type="hidden" name="= Yii::$app->request->csrfParam ?>" value="= Yii::$app->request->getCsrfToken() ?>"> - 前后端域名不一致时,
csrfCookie的domain配置是否覆盖当前页面(比如前端是app.example.com,而 cookie domain 写的是.example.com) - 是否误在 REST 控制器里启用了 CSRF(
yii\rest\ActiveController默认关闭 CSRF,加了public $enableCsrfValidation = true;就会触发)
这类错误不会进模型层,所以无论你怎么改 rules() 或 addError() 都没用——得先让请求成功抵达控制器。


















