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