首页 文章

Yii2 Activerecord根据它们从联结表和订单中获取字段

提问于
浏览
1

我有 itemsunits 表,有很多关系 . 换句话说,该项目有很多单位,单位有很多项目 . 我通过 junctionitem_units 管理了这个关系 . 联结表有一些额外的字段超过 item_idunit_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 شريط"}]

但是,我无法根据 item_units 表中的 weight 字段对结果进行排序,而且我无法在-JSON对象上面的演示结果中包含 price 字段 .

我只能将 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 字段来设置顺序 .

更新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;

3 回答

  • 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);
    }
    
  • 0

    您需要fieldsasArray 在ActiveRecord模型中使用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
    
  • 0

    默认情况下,yii \ base \ Model :: fields()将所有模型属性作为字段返回,而yii \ db \ ActiveRecord :: fields()仅返回已从DB填充的属性 .

    您可以覆盖fields()以添加,删除,重命名或重新定义字段 . fields()的返回值应该是一个数组 . 数组键是字段名称,数组值是相应的字段定义,可以是属性/属性名称,也可以是返回相应字段值的匿名函数 .

相关问题