yii表单验证失败后数据丢失,是因为控制器未将带错误的$model实例传回视图;必须在load()和validate()失败的else分支中render并传入$model,且视图需使用activeform标准写法自动渲染错误。

Yii 表单验证失败时如何保留用户已填数据
验证失败后页面空白或重置,是因为没把 $model 实例传回视图。Yii 的 ActiveForm 依赖模型的当前属性值渲染表单字段,如果控制器里验证失败后没重新 return $this->render(...) 并带上这个带错误的 $model,视图拿到的就是新实例(所有属性为空),自然显示空表单。
实操要点:
- 控制器中必须在
if ($model->load(Yii::$app->request->post()) && $model->validate())的else分支里调用return $this->render('view', ['model' => $model]) - 不要在验证失败时用
redirect,那会丢失$model的状态 - 确保视图里用的是
$form->field($model, 'name')而不是硬编码value="xxx",否则即使模型有值也不会自动填充
为什么 $model->load() 后还要手动调用 $model->validate()
因为 load() 只做属性赋值,不触发验证规则;而 save() 内部会先调用 validate(),但你若想在保存前就展示错误(比如前端不提交、仅校验必填项),就必须显式调用。
常见误区:
- 只写
$model->load(...) && $model->save(),结果验证失败却没报错——save()返回false,但错误信息藏在$model->errors里,没输出到页面 - 误以为
load()成功就等于数据合法,其实它连类型转换都可能失败(比如字符串往int字段赋值) -
load()默认只加载rules()中声明的safe属性,非安全字段需显式指定$model->load($post, '')或改规则
验证失败后如何让错误信息出现在对应字段下方
只要视图里用了 ActiveForm 的标准写法,错误就会自动显示。核心是:$form->field($model, 'email')->textInput() 这个链式调用内部会检查 $model->getErrors('email') 并渲染 <div class="help-block"></div>。
需要注意的细节:
- 确保布局模板里没有禁用错误渲染,比如写了
['errorOptions' => ['class' => 'hidden']]却忘了删 - 自定义表单字段(如用
Html::textInput()替代$form->field())时,必须手动加= $form->errorSummary($model) ?>或逐个调用$form->error($model, 'field') - CSS 类名冲突可能导致错误文字不可见,检查浏览器是否渲染了
.has-error和.help-block元素但被样式覆盖
更新操作中验证失败导致 ID 丢失怎么办
典型场景:编辑页面 URL 是 /post/update?id=123,验证失败后刷新页面变成 /post/update,ID 消失,再提交就变成新增而非更新。根本原因是没在表单里传回 id 字段。
解决方法:
- 在视图中添加隐藏域:
= $form->field($model, 'id')->hiddenInput() ?>(前提是id在rules()中设为safe或显式允许加载) - 或者更稳妥地,在控制器里用
$model->setAttributes(['id' => $id])预设主键,再传给视图 - 避免把
id放在rules()的required列表里——它本不该由用户输入,也不该参与必填校验
复杂点在于,有些开发者会把主键从 rules() 里完全剔除,结果 load() 不认这个字段,又没手动赋值,更新就悄悄变插入。这比验证失败更隐蔽。











