How to display foreign key value instead of key in grid view in yii 2?

65 views Asked by At

Very new to yii, my question is similar to this question How to get foreign key value instead of key in grid view with searching and filtering in yii 2?

I've also seen this wiki https://www.yiiframework.com/wiki/621/filter-sort-by-calculatedrelated-fields-in-gridview-yii-2-0#hh10

I'm not able to figure out what code goes where in the above replies.

I've following tables

CREATE TABLE `customers` (
  `customer_id` int(10) NOT NULL,
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `first_name` varchar(255) DEFAULT NULL,
  `middle_name` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  `country_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

country_id is the foreign key.

CREATE TABLE `countries` (
  `id` int(11) NOT NULL,
  `country` varchar(45) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Grid view

<?= GridView::widget([
    'dataProvider' => $dataProvider,
    'filterModel' => $searchModel,
    'columns' => [
        ['class' => 'yii\grid\SerialColumn'],

        'id',
        'email:email',
        'first_name',
        'middle_name',
        'last_name',
        'country_id',
        [
            'class' => ActionColumn::className(),
            'urlCreator' => function ($action, Customers $model, $key, $index, $column) {
                return Url::toRoute([$action, 'id' => $model->id]);
             }
        ],
    ],
]); ?>

I'm able to show country's id in grid view. How do I show country instead of id?

enter image description here

2

There are 2 answers

1
Serghei Leonenco On BEST ANSWER

You have to use $model instance to get $model value (I assume you defined this in your Customer model and revers method in the country model, also hope you have FK as well when you created your tables) : Customer:

public function getCountry()
{
   return $this->hasOne(Country::class, ['id' => 'country_id]);
}

Then in your grid view:

...
[
    'attribute' => 'country_id',
    'label' => 'Country',
    'value' => function(Customer $model){
       return $model->country->country; // I'm surprised that for the field name you used the same field name as a model, it will be better NAME because it more relevant here 
    },
]
0
SiZE On

The more native way is to specify relation.attribute via dot separator. The label and other data will be automatically retrieved from relation.

Assume that you already have model's relation country.

    GridView::widget([
        // ...
        'columns' => [
            // Example 1. Just get label and value `as is` from relation
            'country.country'

            // Example 2. If you want custom output or label
            [
                'attribute' => 'country.country',
                'format' => 'html',
                'value' => function (Country $model) {
                    return '#' . $model->id . ' <strong>' . $model->country . '</strong>';
                },
            ],
        ],
    ]);