Как использовать несколько моделей в одной форме в 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]) ?>
Что может быть не так?
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, это будет более удобным для пользователя.
Для сохранения отношений читайте — Сохранение отношений.
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
Вы не визуализируете $ modelAgenda из view / update.php для просмотра / _form.php файла, когда используете render в файле обновления.