Yii2 - Saving multiple related ActiveRecord models in one form

Elliot Li picture Elliot Li · May 29, 2015 · Viewed 7.7k times · Source

Here is the table structure:

Table BaseTable
    id (primary key) INT
    description VARCHAR(255)

Table ChildTable
    id (primary key)(foreign key reference to BaseTable) INT
    child_property VARCHAR(255)

It's a inheritance relation in database table actually.

Then I use gii to generate the models with relation function for both, and CRUD operation for ChildTable. Here is the relation function in ChildTable:

public function getBaseTable()
{
    return $this->hasOne(BaseTable::className(), ['id' => 'id']);
}

In the generated form of ChildTable, I'd like to update the property description of it's BaseTable. Here is the original form of ChildTable:

<?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'child_property')->textInput() ?>

<?php ActiveForm::end(); ?>

Try 1:

I add code field below:

<?= $form->field($model, 'baseTable.description')->textInput() ?>

I got this error:

Getting unknown property: app\models\ChildTable::baseTable.description

Try 2:

I ad code field below:

<?= $form->field($model->baseTable, 'description')->textInput() ?>

I got another error:

Call to a member function formName() on null

Try 3:

I use relation to get the BaseTable model, code as below:

<?= $form->field($model->getBaseTable()->one(), 'description')->textInput() ?>

I still got the error:

Call to a member function formName() on null

Idea:

I got a idea that I could create a new viewModel to mapping all the property from BaseTable and ChildTable. But I'd like to know wether there is a fast solution to implement the saving multiple related ActiveRecord models base on the code generated by gii? Thanks!

Answer

arogachev picture arogachev · May 29, 2015

This:

<?= $form->field($model->baseTable, 'description')->textInput() ?>

should work since baseTable is correct relation name. The related record simply doesn't exist (it's null as you can see from error).

It can be either error related with incorrect filling of previous relations or relation is optional.

In the latter case you need to check it for existing (in other words being null) before accessing and displaying.

This: $model->getBaseTable()->one() doesn't make any sense because it equals to $model->baseTable. You should not call relations this way.

And about the way with dot notation - it will not work here.

For loading and saving multiple records you can use:

Then just call save() in loop.