如何在Yii2中以一种形式使用多个模型?
在我的创建操作中,我可以保存到 agenda_fiscalizacao 表中,但在更新中,当我尝试加载表单时收到此错误:
Call to a member function formName() on array
public function actionUpdate($id)
{
$model = $this->findModel($id);
$modelAgenda = AgendaFiscalizacao::findAll(['fiscalizacao_id' => $id]);
if ($model->load(Yii::$app->request->post()) && Model::loadMultiple($modelAgenda, Yii::$app->request->post())) {
$valid = $model->validate();
$valid = $modelAgenda->validade() && $valid;
if ($valid) {
$model->save(false);
$modelAgenda->save(false);
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('update', [
'model' => $model,
'modelAgenda' => $modelAgenda
]);
}
<?= $form->field($modelAgenda, 'agenda_id')->checkboxList(Agenda::combo(), ['class' => 'checkbox']) ?>
<?= $form->field($model, 'bioma_id')->dropDownList(Bioma::combo(), ['prompt' => $prompt]) ?>
<?= $form->field($model, 'nome')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'tipo_doc')->radioList(['CPF'=>'CPF', 'CNPJ'=>'CNPJ'], ['class' => 'radio']) ?>
<?= $form->field($model, 'n_doc')->widget(MaskedInput::className(), ['mask' => ['999.999.999-99', '99.999.999/9999-99']]) ?>
<?= $form->field($model, 'observacao')->textarea(['rows' => 7]) ?>
可能有什么不对?
答案 0 :(得分:7)
1)如果您的意思是使用相同类型的多个模型,则错误在此行中:
$valid = $modelAgenda->validade() && $valid;
首先,它应该是$modelAgenda->validate()
,第二个$modelAgenda
包含模型数组,validate()
方法只能在单个模型上调用。
为了验证多个模型,Yii2建议使用内置方法validateMultiple()
:
use yii\base\Model;
...
$valid = Model::validateMultiple($modelAgenda) && $valid;
官方文档(Collecting Tabular Input)中详细介绍了使用多个模型。
请注意,他们建议在id
之前按照以下内容对模型数组进行索引:
$models = YourModel::find()->index('id')->all();
2)如果您只需要两个不同类型的模型,请不要使用findAll()
,因为它用于查找多个模型并始终返回数组(即使是空结果)。使用new
进行create
操作,findOne()
进行update
操作以初始化模型。假设您初始化了两个模型$firstModel
和$secondModel
,然后您可以加载并保存它们:
$isSuccess = false;
Yii::$app->db->transaction(function () use ($isSuccess) {
$areLoaded = $firstModel->load(Yii::$app->request->post()) && $secondModel->load(Yii::$app->request->post();
$areSaved = $firstModel->save() && $secondModel->save();
$isSuccess = $areLoaded && $areSaved;
});
if ($isSuccess) {
return $this->redirect(['view', 'id' => $model->id]);
}
在保存第二个模型的情况下添加事务将失败(因此第一个模型也不会被保存)。
或者,您可以在模型中声明transactions,例如:
return [
'admin' => self::OP_INSERT,
'api' => self::OP_INSERT | self::OP_UPDATE | self::OP_DELETE,
// the above is equivalent to the following:
// 'api' => self::OP_ALL,
];
然后使用:
$firstModel->scenario = 'scenarioForTransaction';
$secondModel->scenario = 'scenarioForTransaction';
$areLoaded = $firstModel->load(Yii::$app->request->post()) && $secondModel->load(Yii::$app->request->post();
$areSaved = $firstModel->save() && $secondModel->save();
if ($areLoaded && $areSaved) {
return $this->redirect(['view', 'id' => $model->id]);
}
对于两个以上的型号,最好使用循环。
P.S。我建议将保存分离到不同的控制器/操作并通过AJAX调用它,它将更加用户友好。
为了保存关系,请阅读 - Saving Relations。
答案 1 :(得分:2)
public function actionUpdate($id)
{
$model = $this->findModel($id);
$modelAgenda = AgendaFiscalizacao::findAll(['fiscalizacao_id' => $id]);
if ($model->load(Yii::$app->request->post()) && $modelAgenda->load(Yii::$app->request->post()) && Model::validateMultiple([$model, $modelAgenda])) {
$model->save(false);
$modelAgenda->save(false);
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
'modelAgenda' => $modelAgenda
]);
}
您可以参考以下链接,例如:http://blog.dedikisme.com/blog/2014/10/13/yii2-building-a-single-form-with-multiple-models
答案 2 :(得分:0)
在更新文件中使用渲染时,您没有从view / update.php渲染$ modelAgenda以查看/ _form.php文件。