Search code examples
phpyii2gii

Yii2 - Gii Model Relations - Why is there a 0 after the function names?


I haven't seen this online when looking at other's code, guides, tutorials, etc.

When I generate a Model with Gii, the functions regarding relations all have a zero after them.


Example:

class Benefit extends \yii\db\ActiveRecord
{
    // truncated Yii Model code...

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

BenefitTypes is an id to name mapping:

id | name
---------------
1  =>  Federal
2  =>  Non-Profit

In the 'benefit' table, it has column named 'type' that is a relation to the 'benefit_types' table 'id' column.

I though I should be able to do (in /views/benefit/index.php) 'type.name' but it doesn't work either. It changes the column name to "Type Name" and puts "(not set)" in the data table...

Example:

<?= DetailView::widget([
    'model' => $model,
    'attributes' => [
        'id',
        'somevalue',
        'type.name',
    ],
]) ?>

What is going on, why does it not act like it's supposed to?


UPDATE

I am beginning to think the 0 suffix to the relation function names, ie: getType0, is due to "type" being used in the table as a column name to avoid duplication or confusion. I can't find this documented though, so would like to have a definite answer on that.

I changed the function name to getTypeRelation(). Then in the index.php view, for the detailview widget, used 'typeRelation.name' and it returned the name through the relation just fine.


Solution

  • Your thinking is correct. Generation of the relation names is done by the function generateRelationName().

    protected function generateRelationName($relations, $table, $key, $multiple)
    {
        if (!empty($key) && substr_compare($key, 'id', -2, 2, true) === 0 && strcasecmp($key, 'id')) {
            $key = rtrim(substr($key, 0, -2), '_');
        }
        if ($multiple) {
            $key = Inflector::pluralize($key);
        }
        $name = $rawName = Inflector::id2camel($key, '_');
        $i = 0;
        while (isset($table->columns[lcfirst($name)])) {
            $name = $rawName . ($i++);
        }
        while (isset($relations[$table->fullName][$name])) {
            $name = $rawName . ($i++);
        }
        return $name;
    }
    

    Yii uses the related table's name as the relation name. Should you have a column with the same name as the related table, a digit will be appended to the relation to avoid confusion due to Yii's handling of magic functions. This also occurs if you have two columns or more in a single table related to the same table e.g columns create_user_id, update_user_id and delete_user_id related to table user will result in relations named user, user0 and user1.

    For your example, it is advisable to name your foreign key field something else e.g type_id or typeId. Yii will handle these correctly . The other alternative when you have multiple columns related to the same table is to just rename the functions.