I have items
and units
table that have many to many relationship. In other words, the item has many units and the unit has many items. I managed the relation through a junction table item_units
. The junction table has some extra field more than item_id
and unit_id
, i.e it has price, and weight (it is an integer to manage the order of units for each item for display purposes).
I managed the relations in the models as follows:
//In Items model
/**
* @return \yii\db\ActiveQuery
*/
public function getItemUnits()
{
return $this->hasMany(ItemUnits::className(), ['item_id' => 'id'])->orderBy(['item_units.weight' => SORT_DESC]);
}
public function getUnits()
{
return $this->hasMany(Units::className(), ['id'=> 'unit_id'])->select(['id','title'])->via('itemUnits');
}
//
//In Units model
public function getItemUnits()
{
return $this->hasMany(ItemUnits::className(), ['unit_id' => 'id'])->orderBy(['price' => SORT_DESC]);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getItems()
{
return $this->hasMany(Items::className(), ['id' => 'item_id'])->via('itemUnits');
}
//
//In ItemUnits model
public function getItem()
{
return $this->hasOne(Items::className(), ['id' => 'item_id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getUnit()
{
return $this->hasOne(Units::className(), ['id' => 'unit_id']);
}
In the controller I'm able to get the data of all related units to an item by something like the following:
$item = Items::findOne($id);
return Json::encode($item->units);
The following is a demo of the JSON object obtained:
[{"id":"4","title":"قرص"},{"id":"5","title":"شريط 10"},{"id":"6","title":"علبة 2 شريط"}]
However, I could not able to order the results according to the weight
field in item_units
table and also I could not able to include the price
field there in the demo result above -JSON Object-.
I only able to get data in item_units
as a separate result like the following:
return Json::encode($item->itemUnits);
Update
According to the two answers (@Александр Шалаев & @Onedev.Link) , I have overridden the fields
method in Units model as follows:
public function fields() {
parent::fields();
return [
'price' => function($model){
return $model->id; //Here I could not able to get the corresponding price field value from item_units -junction table-
},
'id',
'title',
];
}
However, I could not able to get the price
field value from the junction table, temporary, I set it to current model id to prevent error generation. Also, I still has no any mean to set order by using weight
field in that junction table.
Update 2
In other words, how could Yii2 Activerecords perform the following SQL query:
SELECT units.id UnitID, units.title Unit, iu.weight, iu.price
FROM units
Left JOIN item_units AS iu
ON iu.item_id = 1 AND iu.unit_id = units.id
WHERE
units.id = iu.unit_id
ORDER BY iu.weight;