Yii 2 Active Record嵌套了多个关系

时间:2018-01-17 09:05:34

标签: php activerecord yii many-to-many nested-query

我有4个表产品,属性,property_items,property_product,关系像这样 产品有很多属性。 物业有很多property_items。 产品有很多property_items。 Property_product是中间表。

-- products --
Id   name
1   Arrabiata
2   Bolognese

--properties --
Id   name
1   Pasta type
2   Size

-- property_items --
Id   name                   value      property_id
1    Spinach spaghetti      .....      1
2    Linguine               .....      1
3    Spaghetti              .....      1
4    Small                  ....       2
5    Medium                 ....       2
6    Large                  ...        2

-- property_product  -- 
product_id    property_id  property_item_id
    1             1              1
    1             1              2
    1             2              4
    1             2              6
    2             1              2
    2             1              3
    2             2              5

我尝试使用Gii创建具有关系的模型。

class Products extends \yii\db\ActiveRecord
{
    //code
    ....

    public function getProperties()
    {
        return $this->hasMany(Properties::className(), ['id' => 'property_id'])
                    ->viaTable('property_product', ['product_id' => 'id']);
    }
}

class Properties extends \yii\db\ActiveRecord
{
  //code
  ...

  public function getPropertyItems()
    {
        return $this->hasMany(PropertyItems::className(), ['property_id' => 'id']);
    }
}

我想查询具有多嵌套关系的数据。 如何在一个活动记录查询中创建具有以下格式的json响应?

[
{
    "id": "1",
    "name": "Arrabiata",
    "properties": [
        {
            "id": "1",
            "name": "Pasta type",
            "property_items" : [
                {
                    "id": "1",
                    "name": "Spinach spaghetti",
                },
                {
                    "id": "2",
                    "name": "Linguine",
                },
            ]
        },
        {
            "id": "2",
            "name": "Size",
            "property_items" : [
                {
                    "id": "4",
                    "name": "Small",
                },
                {
                    "id": "6",
                    "name": "Large",
                },
            ]
        },
    ],
},
{
    "id": "2",
    "name": "Bolognese",
    "properties": [
        {
            "id": "1",
            "name": "Pasta type",
            "property_items" : [
                {
                    "id": "2",
                    "name": "Linguine",
                },
                {
                    "id": "3",
                    "name": "Spaghetti",
                },
            ]
        },
        {
            "id": "2",
            "name": "Size",
            "property_items" : [
                {
                    "id": "5",
                    "name": "Medium",
                },
            ]
        },
    ]
}]

我使用此查询但性能过高

Menus::find()->with(['products' => function ($query) {
            $query->with(['properties']);
        }])
        ->where(['>', 'status', 0])
        ->andWhere(['resid' => $id])->asArray()->all();;
        foreach ($menus as &$menu) {
            foreach ($menu['products'] as &$product) {
                foreach ($product['properties'] as &$property) {
                    $propertyItems = PropertyItems::find()->where(['property_id' => $property['id']]
                    )
                    ->leftJoin('property_product', 'property_items.id = property_product.property_item_id')
                    ->where(['property_product.product_id' => $product['id'],
                             'property_product.property_id' => $property['id']])
                    ->asArray()->all();
                    $property['propertyItems'] = $propertyItems;
                }
            }
        }

如果我使用此查询

Menus::find()->with(['products' => function ($query) {
                                        $query->with(['properties' => function ($query) {
                                            $query->with(['propertyItems']);
                                        }
                                        ]);
                                    }
                          ])->asArray()->all();

但结果与我预期的结果不一样,因为所有property_items都会显示在属性中,而不是依赖于通过表" property_product"

与产品相关联
[
{
    "id": "1",
    "name": "Arrabiata",
    "properties": [
        {
            "id": "1",
            "name": "Pasta type",
            "property_items" : [
                {
                    "id": "1",
                    "name": "Spinach spaghetti",
                },
                {
                    "id": "2",
                    "name": "Linguine",
                },
                {
                    "id": "3",
                    "name": "Spaghetti",
                },
            ]
        },
        {
            "id": "2",
            "name": "Size",
            "property_items" : [
                {
                    "id": "4",
                    "name": "Small",
                },
                {
                    "id": "6",
                    "name": "Large",
                },
                {
                    "id": "5",
                    "name": "Medium",
                },
            ]
        },
    ],
},
{
    "id": "2",
    "name": "Bolognese",
    "properties": [
        {
            "id": "1",
            "name": "Pasta type",
            "property_items" : [
                {
                    "id": "1",
                    "name": "Spinach spaghetti",
                },
                {
                    "id": "2",
                    "name": "Linguine",
                },
                {
                    "id": "3",
                    "name": "Spaghetti",
                },
            ]
        },
        {
            "id": "2",
            "name": "Size",
            "property_items" : [
                {
                    "id": "4",
                    "name": "Small",
                },
                {
                    "id": "6",
                    "name": "Large",
                },
                {
                    "id": "5",
                    "name": "Medium",
                },
            ]
        }
    ]
}]

提前致谢。

1 个答案:

答案 0 :(得分:0)

您必须覆盖fields()Products模型的Properties功能。

例如:

class Products extends ActiveRecord {

 function fields(){
    return ['properties'];
   }
 }


class Properties extends ActiveRecord {

     function fields(){
        return ['property_items'];
     }
 }