Related models are not set in dataProvider

Hello

I’m using Yii2 for a while now, but the following issue confuses me:

I Have three models ComputerComputerSearch and Mainboard
The Mainboard has a 1:1 relation with Computer.
In Computer I have the following Code:

public function getMainboard(){
   return $this->hasMany(Mainboard::className(), ['computer_id', 'id']);
}

In the view I have a table, which should show columns of Computer (id, name and serial_number) and the type of the mainboard (mainboard.type), which is stored in the mainboard table, so I join it as following:

    echo GridView::widget([
      'dataProvider' => $dataProvider,
      'filterModel' => null,
      'columns' => [
        'id',
        'name',
        'mainboard.type',
        'serial_number',

      ],
    ]);

This works so far and there is nothing wrong.

The problem comes now:
The user also needs to filter/search for the type-field from the Model Computer.
Because of that, I have to join with the mainboard relation in the search() method of ComputerSearch, which looks as following:

public function search($params) {
      $query = Computer::find();
      $query->innerJoinWith('mainboard');

      //...

     var_dump($dataProvider[0]->mainboard); //first dump
     var_dump($query->createCommand()->rawSql); //second dump
     exit;
     return $dataProvider;
}

the result of the “first dump” is null, no matter which index of the $dataProvider I take. According to the database every Computer has a Mainboard. If I copy the result of the “second dump” into the sql and execute it manually I get a correct result, and - apparently - every computer record has a mainboard record.

When the related mainboard Model is not in the $dataProvider, it will show “(not set)” in the Gridview for the mainboard.type column.

I found out, that the related mainboard Model is set if I do the join manually by $query->join() instead of $query->innerJoinWith(), but I don’t like this workaround.

I think this is an issue from the yii framework.
Somebody else knows this issue or can somebody explain me, why it doesn’t work with $query->innerJoinWith()?

Hi @Migly, welcome to the forum.

The data provider is not an array of retrieved records. If you wanted to access the records, you had to call getModels() method.

var_dump($dataProvider->models[0]->mainboard); //first dump

Please check the following section of the guide:
Guide > Displaying Data > Data Provider > Active Data Provider

And one more thing.

There is a drawback in this definition of a relation, because you have to write like the following to refer to the mainboard.

$computer->mainboard[0]

The relation above could be defined as hasOne:

public function getMainboard(){
    return $this->hasOne(Mainboard::className(), ['computer_id', 'id']);
}

As you see in the API reference, $link (the 2nd parameter) should be an array whose key is a column from mainboard and value is one from computer. So it will work as expected when there is actually at most 1 mainboard per a computer although the schema would allow multiple mainboards.

Hey @softark

Thank you verey much for your interest in the problem. Both issues you mentioned happend, while I was anonymizing the code. So my original code already contained those two “improvements” you mentioned.

BTW: (How) Can I edit my original post?

You’ll find a button with a pencil under your post. It’s the button for editing.