Yii2中提交表单时Clinic表数据无法保存的问题求助
Yii2多表数据保存问题解决
你的代码存在三个核心问题,直接导致clinic表无法正常保存数据,下面逐个解决:
1. SignupForm模型未接收诊所相关字段
视图里用了$model2的clinicName和clinicArea字段,但SignupForm模型没有定义这两个属性,表单提交的数据根本传不到signup方法里的Clinic实例中。
修改SignupForm模型:
class SignupForm extends Model { // 原有属性 public $username; public $email; public $password; // 添加诊所相关属性 public $clinicName; public $clinicArea; // 补充验证规则 public function rules() { return [ // 原有规则 ['username', 'trim'], ['username', 'required'], ['username', 'unique', 'targetClass' => '\app\models\User', 'message' => 'This username has already been taken.'], ['username', 'string', 'min' => 2, 'max' => 255], ['email', 'trim'], ['email', 'required'], ['email', 'email'], ['email', 'string', 'max' => 255], ['email', 'unique', 'targetClass' => '\app\models\User', 'message' => 'This email address has already been taken.'], ['password', 'required'], ['password', 'string', 'min' => 6], // 诊所字段规则 [['clinicName', 'clinicArea'], 'required'], [['clinicName', 'clinicArea'], 'string', 'max' => 255], ]; } }
2. 控制器逻辑混乱,重复处理Clinic模型
你在控制器里同时加载了$model和$model2,但又调用$model->signup()(里面也新建了Clinic实例),而且不管signup是否成功,直接执行$model2->save()并跳转,这会导致:
- signup方法里的Clinic实例拿不到表单数据
- 可能重复保存空的Clinic记录
- 错误被隐藏,无法定位保存失败原因
修改SiteController的actionSignup方法:
public function actionSignup() { $model = new SignupForm(); if ($this->request->isPost) { if ($model->load(Yii::$app->request->post()) && $user = $model->signup()) { // 仅当signup全部流程成功时跳转 Yii::$app->session->setFlash('success', 'Thank you for registration. Please check your inbox for verification email.'); return $this->goHome(); } // 若失败,表单会自动显示错误信息,无需额外处理 } return $this->render('signup', [ 'model' => $model, ]); }
3. signup方法添加事务保证数据一致性
原来的signup方法用&&连接保存操作,若User保存成功但Clinic保存失败,会造成数据不一致。需要用事务包裹操作,确保两个表的保存要么都成功,要么都回滚。
修改SignupForm的signup方法:
public function signup() { if (!$this->validate()) { return null; } // 开启数据库事务 $transaction = Yii::$app->db->beginTransaction(); try { $user = new User(); $user->username = $this->username; $user->email = $this->email; $user->setPassword($this->password); $user->generateAuthKey(); $user->generateEmailVerificationToken(); if (!$user->save()) { throw new \Exception('用户信息保存失败'); } $clinic = new Clinic(); $clinic->Id = $user->id; // 注意:若你的Clinic表主键是小写`id`,请改为$clinic->id $clinic->clinicName = $this->clinicName; $clinic->clinicArea = $this->clinicArea; if (!$clinic->save()) { throw new \Exception('诊所信息保存失败'); } if (!$this->sendEmail($user)) { throw new \Exception('验证邮件发送失败'); } // 提交事务 $transaction->commit(); return $user; } catch (\Exception $e) { // 回滚事务,撤销所有修改 $transaction->rollBack(); // 将错误信息添加到模型,前端可显示 $this->addError(null, $e->getMessage()); return null; } }
4. 视图调整(同步修改)
现在不需要$model2了,同步修改视图文件:
signup视图:
<div class="site-signup"> <h1><?= Html::encode($this->title) ?></h1> <?= $this->render('signupnew', [ 'model' => $model, ]) ?> </div>
signupnew视图:
<div class="site-signup"> <p>Please fill out the following fields to signup:</p> <div class="row"> <div class="col-lg-5"> <?php $form = ActiveForm::begin(['id' => 'form-signup']); ?> <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?> <?= $form->field($model, 'email') ?> <!-- 改用$model的属性绑定字段 --> <?= $form->field($model, 'clinicName')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'clinicArea')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'password')->passwordInput() ?> <div class="form-group"> <?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?> </div> <?php ActiveForm::end(); ?> </div> </div> </div>
调试技巧
如果仍保存失败,可在$clinic->save()前打印错误信息排查:
var_dump($clinic->errors);die;
内容的提问来源于stack exchange,提问作者Meow
相关产品推荐
相关产品推荐

