laravel 如何对属性值进行分组?

iyfjxgzm  于 2023-01-27  发布在  其他
关注(0)|答案(1)|浏览(132)

如何得到这个结果:

foreach ($products as $product) {
    $product->name

    foreach ($product->attributes as $attribute) {
        $attribute->name

        foreach ($attribute->values as $value) {
            $value->name
        }
    }
}

还有

{
    "name": "Product",
    "attributes": [
        {
            "name": "Attribute 1",
            "values": [
                "name": "Value 1",
                "name": "Value 2",
            ]
        }
    ]
}

而不是这个:

foreach ($products as $product) {
    $product->name

    foreach ($product->attributeValues as $attributeValue) {
        $attributeValue->attribute->name
        $attributeValue->name
    }
}

还有

{
    "name": "Product",
    "attribute_values": [
        {
            "attribute_name": "Attribute 1",
            "value_name": "Value 1",
        },
        {
            "attribute_name": "Attribute 1",
            "value_name": "Value 2",
        }
    ]
}

数据库

products
--- id
--- name

attributes
--- id
--- name

attribute_values
--- id
--- attribute_id
--- name

attribute_value_product
--- id
--- attribute_value_id
--- product_id

产品

  • 属性值的多对多关系。
    属性
  • 属性值的一对多关系。
    属性值
  • 属性的一对多(属于)关系。
  • 产品的多对多关系。

我正在努力寻找解决方案,但失败了,所以我张贴在这里获得一些解决方案。
请帮帮我。

suzh9iv8

suzh9iv81#

您所需的输出

"values": [
    "name": "Value 1",
    "name": "Value 2",
]

这不是一个有效的JSON,你不能有一个数组有相同的键,你要么删除键,要么把数组中的每个值 Package 成一个键名。
无论如何,您只需在产品中定义关系以提取属性值,并在属性值中为属性名称建立关系,
像这样事情,

产品型号

// get the attribute_values assign to products
public function attributeValues() {
    return $this->belongsToMany(AttributeValue::class);
}

属性值模型

// get the attribute name assign to attribute value
public function attrName() {
    return $this->belongsTo(Attribute::class, 'attribute_id');
}

然后,您可以查询相关关系并修改attribute_values以适合您所需的格式。
样品;
假设你有这个属性

[{ id: 1, name: "weight" }, { id: 2, name: "style" }, { id: 3, name: "color" } ]

创建您的产品

Product::create([
    'name' => 'Product 2'
])->attributeValues()->createMany([
    ['attribute_id' => 1, 'name' => '1.3kg'],
    ['attribute_id' => 2, 'name' => 'something nice'],
    ['attribute_id' => 3, 'name' => 'yellow'],
    ['attribute_id' => 3, 'name' => 'black'],
    ['attribute_id' => 3, 'name' => 'orange'],
]);

然后您的产品查询

// eager load attribute values and attribute values name relationship
$products = Product::select('id','name')
    ->with(['attributeValues', 'attributeValues.attrName' ])
    ->paginate();

// modify and format the attribute values according to your needs before returning the products 
// refer to Laravel Collection docs on how you can modify a collection and its data
$products->map( function($item) {
    $item->attributes = collect($item->attributeValues)
        ->groupBy('attrName.id')
        ->values()
        ->map(fn ($group, $key) => [
            'name' => data_get($group, '0.attrName.name'),
            'values' => $group->pluck('name')->all()
        ])
        ->values();
        
    //Remove the original attributeValues data 
    unset($item['attributeValues']);
    return $item;
});
    
// Return the paginated products
return $products;

您应该获得如下的产品数据格式

{
    id: 2,
    name: "Product 2",
    attributes: [
        {
            name: "weight",
            values: [
                "1.3kg"
            ]
        },
        {
            name: "style",
            values: [
                "something nice"
            ]
        },
        {
            name: "color",
            values: [
                "yellow",
                "black",
                "orange"
            ]
        }
    ]
}

此外,您可以在Product模型中附加一个预先格式化的自定义属性值,每次查询产品时都会自动加载该值。
例如产品型号

protected $appends = ['attributes'];

public function attributeValues() {
    return $this->belongsToMany(AttributeValue::class);
}

protected function getAttributesAttribute() {
    return $this->attributeValues()->get()
            ->groupBy('attrName.id')
            ->values()
            ->map(fn ($group, $key) => [
                'name' => data_get($group, '0.attrName.name'),
                'values' => $group->pluck('name')->all()
            ])
            ->values();
}

你就可以用

return Product::select('id','name')->paginate();

return Product::find(1);

属性属性将自动出现在响应中
上面的代码使用了集合方法groupBy、map、values。有关详细信息,请查看集合docs

相关问题