Yii2 несколько моделей в одной форме

Как использовать несколько моделей в одной форме в 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]) ?>

Что может быть не так?

введите описание изображения здесь

5

Решение

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() потому что это для поиска нескольких моделей и всегда возвращает массив (даже при пустом результате). использование 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]);
}

Транзакция добавляется в случае, если сохранение второй модели не удастся (поэтому первая модель также не будет сохранена).

Кроме того, вы можете объявить операции внутри вашей модели, например:

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

Для более чем двух моделей лучше использовать петли.

Постскриптум Я бы рекомендовал разделить сохранение на разные контроллеры / действия и вызывать его через AJAX, это будет более удобным для пользователя.

Для сохранения отношений читайте — Сохранение отношений.

7

Другие решения

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

0

Вы не визуализируете $ modelAgenda из view / update.php для просмотра / _form.php файла, когда используете render в файле обновления.

0
По вопросам рекламы [email protected]