我有items
和units
表,它们有很多关系。换句话说,该项目有很多单位,单位有很多项目。我通过结表item_units
管理了该关系。联结表有一些额外的字段超过item_id
和unit_id
,即它有价格和权重(它是一个整数来管理每个项目的单位顺序以便显示)。
我在模型中管理了如下关系:
//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']);
}
在控制器中,我能够通过以下内容获取所有相关单元的数据:
$item = Items::findOne($id);
return Json::encode($item->units);
以下是获得的JSON对象的演示:
[{"id":"4","title":"قرص"},{"id":"5","title":"شريط 10"},{"id":"6","title":"علبة 2 شريط"}]
但是,我无法根据weight
表格中的item_units
字段订购结果,而且我无法在上面的演示结果中包含price
字段-JSON对象 - 。
我只能将item_units
中的数据作为单独的结果获取,如下所示:
return Json::encode($item->itemUnits);
根据这两个答案(@АлександрШалаев& @ Onedev.Link),我在 Units 模型中覆盖了fields
方法,如下所示:
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',
];
}
但是,我无法从联结表中获取price
字段值,临时,我将其设置为当前模型ID以防止错误生成。此外,我仍然没有任何意思通过在该联结表中使用weight
字段来设置顺序。
换句话说,Yii2 Activerecords如何执行以下SQL查询:
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;
答案 0 :(得分:1)
最后我找到了解决方案。这取决于findBySql
方法。我将使用 Update 2 - 中所考虑的上述SQL查询,我已删除了一些适合我当前任务的选定字段 - 。
public function actionUnitsJson($id){
$sql = 'SELECT units.id, units.title
FROM units
Left JOIN item_units AS iu
ON iu.item_id = :id AND iu.unit_id = units.id
WHERE
units.id = iu.unit_id
ORDER BY iu.weight DESC;';
$units = \common\models\Units::findBySql($sql,[':id' => $id])->asArray()->all();
return Json::encode($units);
}
答案 1 :(得分:0)
您的ActiveRecord模型中asArray
需要fields或extraFields。
示例:
/**
* @return array
*/
public function fields()
{
return [
'itemUnit', //will get getItemUnit method
];
}
or
/**
* @return array
*/
public function extraFields()
{
return [
'itemUnits', //it is relation name
];
}
用法:
$model->toArray(); //will contains fields and extra fields relations
... sort array & return
答案 2 :(得分:0)
默认情况下,yii \ base \ Model :: fields()将所有模型属性作为字段返回,而yii \ db \ ActiveRecord :: fields()仅返回从DB填充的属性。
您可以覆盖字段()以添加,删除,重命名或重新定义字段。 fields()的返回值应该是一个数组。数组键是字段名称,数组值是相应的字段定义,可以是属性/属性名称,也可以是返回相应字段值的匿名函数。