Gii to create dropdowns for relations

Can anybody help me on how to create with Gii automatically dropdowns for related tables?

I havenā€™t tried it but if it is something on big scale you can customize giiā€™s templates: https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide/2.2/en/topics-creating-your-own-templates#creating-your-own-templates

If not, it is not worth it. It is pretty easy to customize code you got from gii. All in all displaing dropdowns is more or less something like this: https://www.yiiframework.com/doc/guide/2.0/en/input-forms#creating-activeform-dropdownlist

To be more related to your question, you can easily get the dropdown items from related table, like this:

$items = Related::find()->select(['id' ,'value'])
  ->where['relatedId' => $model->id]->all();
echo $form->field($model, 'category')
  ->dropdownList($items,
  ['prompt'=>'Select...']);
1 Like

Thanks for your reply Bart, you opend my eyes.

I checked in /var/www/html/blender-admin/vendor/yiisoft/yii2-gii/src/generators/crud/Generator.php

and I found a public function generateActiveField($attribute)
within this code:


if (is_array($column->enumValues) && count($column->enumValues) > 0) {
            $dropDownOptions = [];
            foreach ($column->enumValues as $enumValue) {
                $dropDownOptions[$enumValue] = Inflector::humanize($enumValue);
            }
            return "\$form->field(\$model, '$attribute')->dropDownList("
                . preg_replace("/\n\s*/", ' ', VarDumper::export($dropDownOptions)).", ['prompt' => ''])";
        }

This block of code produce a dropdown for enum datatype in MySQL.

I figured out, that to solve my question I have to somehow figure out how to check for foreign key (https://www.yiiframework.com/doc/api/2.0/yii-db-foreignkeyconstraint) and add some code on this point.

Does anybody else already did this?

Iā€™m not sure what is your point but if your ActiveRecord models have relations to each other you can simply reach for related object id simply accesing $model->related[n]->id. Many ways here are possible.

1 Like

I very typically add the following static method to the related model:

static public function dropDownList()
    {
	    return \yii\helpers\ArrayHelper::map(self::find()->orderBy('sort')->all(),'id','title');
    }

I then modify the orderBy and the ā€˜titleā€™ to match the related model particulars.

Then in my form I use something like

<div class='col-sm-3'><?= $form->field($model, 'related_model_id')->dropDownList(\app\models\RelatedModel::dropDownList(),['prompt'=>'select..']); ?></div>

2 Likes

Thanks for your tips.

Still stucked with gii generators. Perhaps anyone already have a solution on how to automatically generate dropdowns in GII for the related tables?

vendor/yiisoft/yii2-gii/src/generators/crud/Generator.php

What is so specific in your scenario that you cannot add these dropdowns by hand? Are there that much tables on which you need generate dropdown to related?

1 Like

Yes and beside this Iā€™m lazy :slight_smile:
And the idea of creating appz overnight (once you have a DB) it is mindblowing :wink:

My idea is also to chenge the generators to use Kartik components.

Regards Luka

Can I use the above approach in a static way?

I have a command that must be attributed to any device. I am trying to display all devices (respecting current relation in ā€œeditā€ view or without relation in ā€œcreateā€ view).

I am trying to achieve the same as OP, but the following way.

Model:

public static function getAllDevices()
{
    return self::find()->select(['id', 'name'])->where(['>=', 'type', 1])->all();
}

Controller:

return $this->render('create', [
    'model' => $model,
    'devices' => Device::getAllDevices(),
]);

View:

<?= $form->field($model, 'to')->dropdownList($devices); ?>

I am getting the following error instead of the expected results:

Object of class common\models\Device could not be converted to string

I know that I must be missing something obvious, but I canā€™t find what.

The magic ingredients here are ->asArray() and ArrayHelper::map which are also missed in my example, been written ad hoc from memory.

So try:

return ArrayHelper::map(self::find()->select(['id', 'name'])->asArray()
  ->where(['>=', 'type', 1])->all(),
'id', 'name');
2 Likes

Works like a charm, thank you!

1 Like

@samdark any idea?