Reputation: 454
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
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