8

Yii2中如何以一种形式使用多个模型?

我的情况: ER图

在我的创建操作中,我可以保存到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]) ?>    

有什么问题?

编辑(完全错误):

在此处输入图像描述

4

3 回答 3

9

1)如果您的意思是使用相同类型的多个模型,则错误在此行:

$valid = $modelAgenda->validade() && $valid;

首先,它应该是$modelAgenda->validate(),其次$modelAgenda包含模型数组,validate()方法只能在单个模型上调用。

为了验证多个模型 Yii2 建议使用内置方法validateMultiple()

use yii\base\Model;

...

$valid = Model::validateMultiple($modelAgenda) && $valid;

官方文档(收集表格输入)很好地涵盖了使用多个模型。

请注意,他们建议id像这样索引模型数组:

$models = YourModel::find()->index('id')->all();

2)如果您只需要两个不同类型的模型,请不要使用findAll(),因为它用于查找多个模型并且总是返回数组(即使是空结果)。使用newfor createaction 和findOne()for updateaction 来初始化模型。假设您初始化了两个模型,$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]);
}

在保存第二个模型失败的情况下添加事务(因此第一个模型也不会保存)。

或者,您可以在模型中声明事务,例如:

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]);
}

对于两个以上的模型,最好使用循环。

PS我建议分开保存到不同的控制器/动作并通过AJAX调用它,它会更加用户友好。

要保存关系,请阅读 -保存关系

于 2016-01-26T16:38:47.690 回答
3
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

于 2017-08-21T09:36:20.407 回答
0

在更新文件中使用渲染时,您不会将 $modelAgenda 从 view/update.php 渲染到 view/_form.php 文件。

于 2017-08-22T10:22:20.297 回答