Roman Andreev
Roman Andreev

Reputation: 454

Yii2 polymorphic relations in ActiveRecord and GridView behavior

I have tried to implement polymorphic relation in Yii2 ActiveRecord, but I faced the problem.
So, I have the following DB structure:

Ticket Table

+----+-------+
| id | type  |
+----+-------+
|  1 |     1 |
|  1 |     2 |
|  1 |     3 |
+----+-------+

TicketOne Table

+----+--------------+---------------------+
| id |   relation   |   anotherRelation   |
+----+--------------+---------------------+
|  1 | ticketOneRel | ticketOneAnotherRel |
|    |              |                     |
+----+--------------+---------------------+

TicketTwo table

+----+--------------+---------------------+
| id |   relation   |   anotherRelation   |
+----+--------------+---------------------+
|  1 | ticketTwoRel | ticketTwoAnotherRel |
|    |              |                     |
+----+--------------+---------------------+

In the Ticket Active Record model I implement these methods:

public function getTicket()
    {
        switch ($this->type){
            case self::TYPE_CLIENT:
                return $this->getTiektOne();
            case self::TYPE_STAFF:
                return $this->getTicketTwo();
            default:
                throw new \RuntimeException('Appeal type is wrong!');
        }
    }


public function getTicketOne()
{
    return $this->hasOne(TicketOne::className(), ['EXT_ID' => 'FID_APPEAL']);
}

public function getTicketTwo()
{
    return $this->hasOne(TicketTwo::className(), ['EXT_ID' => 'FID_APPEAL']);
}

Both child Ticket models have getRelation() and getAnotherRelation() methods that return the corresponding fields.

To show all the tickets I use GridView widget. In the TiecktSearch model I make $dataProvider:

$query = Ticket::find()
    ->with('ticket')
    ->with('ticket.relation')
    ->with('ticket.anotherRelation');

$dataProvider = new ActiveDataProvider([
    'query' => $query,
]);

So, when I filter GridView to show one kind of tickets type it works fine. But if I use not filtered GridView odd things begin to happen.
For example: if the first GridView row has type TicketOne, all the tickets with type "One" are showing well. But TicketTwo type tickets breaks.
The problem is when I get ticket.relation on GridView column, it behaves like this relation gets data from TypeOne ticket: in the "relation" GridView field it shows ticketOneRel when it really should be ticketTwoRel

Upvotes: 0

Views: 483

Answers (1)

DrBorrow
DrBorrow

Reputation: 958

I don’t think your approach is possible. You are asking Yii to do a different left join per row in Gridview but this is not how it works. Yii is trying to build one query to supply all your data.

Instead, you can create a stand-alone function that will perform an independent query per row

public function getTicket(){
   If ($this->type == self::TYPE_CLIENT)
      $model = new TicketOne::find();
   else
       $model = new TicketTwo::find();

   $model->select(...
   return $model->getOne();

If you are only retuning one or two columns in the Gridview, this should be fine. However if you have a lot of columns this will slow your site down a lot.

Upvotes: 0

Related Questions