You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对属性值进行分组?实现嵌套式产品属性数据结构

解决方案:将扁平产品属性结构转换为嵌套分组结构

方法一:PHP端重组已获取的扁平数据

假设你已经通过ORM或原生查询拿到了包含attribute_values关联的产品集合,可以通过遍历分组重构嵌套结构:

代码示例(PHP)

// 假设$products是从数据库获取的产品集合,每个产品包含attributeValues关联
$transformedProducts = [];

foreach ($products as $product) {
    // 初始化当前产品的嵌套结构
    $transformedProduct = [
        'name' => $product->name,
        'attributes' => []
    ];
    
    // 按属性ID分组属性值
    $attributeGroups = [];
    foreach ($product->attributeValues as $attrValue) {
        $attrId = $attrValue->attribute->id;
        // 初始化属性分组
        if (!isset($attributeGroups[$attrId])) {
            $attributeGroups[$attrId] = [
                'name' => $attrValue->attribute->name,
                'values' => []
            ];
        }
        // 添加属性值到对应分组
        $attributeGroups[$attrId]['values'][] = [
            'name' => $attrValue->name
        ];
    }
    
    // 将分组后的属性转为数组,加入产品结构
    $transformedProduct['attributes'] = array_values($attributeGroups);
    $transformedProducts[] = $transformedProduct;
}

// 输出格式化后的JSON
echo json_encode($transformedProducts, JSON_PRETTY_PRINT);

方法二:SQL查询直接获取分组结构(更高效)

通过SQL关联查询并按属性分组,一次性获取嵌套结构的基础数据,减少PHP端处理量:

SQL查询语句

SELECT
    p.id AS product_id,
    p.name AS product_name,
    a.id AS attribute_id,
    a.name AS attribute_name,
    JSON_ARRAYAGG(JSON_OBJECT('name', av.name)) AS attribute_values
FROM products p
JOIN attribute_value_product avp ON p.id = avp.product_id
JOIN attribute_values av ON avp.attribute_value_id = av.id
JOIN attributes a ON av.attribute_id = a.id
GROUP BY p.id, p.name, a.id, a.name
ORDER BY p.id, a.id;

PHP端整理最终结构

// 执行上述SQL后获取结果集$rows
$products = [];
foreach ($rows as $row) {
    $productId = $row['product_id'];
    if (!isset($products[$productId])) {
        $products[$productId] = [
            'name' => $row['product_name'],
            'attributes' => []
        ];
    }
    $products[$productId]['attributes'][] = [
        'name' => $row['attribute_name'],
        'values' => json_decode($row['attribute_values'], true)
    ];
}

// 转换为最终数组并输出JSON
$finalProducts = array_values($products);
echo json_encode($finalProducts, JSON_PRETTY_PRINT);

方法三:ORM关联定义(以Laravel Eloquent为例)

通过模型关联和访问器自动生成嵌套结构:

  1. 在Product模型中定义关联与访问器:
class Product extends Model
{
    // 产品与属性值的多对多关联
    public function attributeValues()
    {
        return $this->belongsToMany(AttributeValue::class, 'attribute_value_product');
    }

    // 自动生成嵌套attributes结构的访问器
    public function getAttributesAttribute()
    {
        return $this->attributeValues->groupBy('attribute.id')->map(function ($values) {
            return [
                'name' => $values->first()->attribute->name,
                'values' => $values->pluck('name')->map(fn($name) => ['name' => $name])
            ];
        })->values();
    }

    // 隐藏原扁平关联字段
    protected $hidden = ['attributeValues'];
}
  1. 使用时直接获取并输出JSON:
$products = Product::with('attributeValues.attribute')->get();
echo $products->toJson(JSON_PRETTY_PRINT);

注意事项

  • 你提供的期望JSON结构中values数组格式有误,正确格式应为包含多个{"name": "值名称"}对象的数组,上述代码已按正确格式输出。
  • 使用ORM时需预加载关联(如with('attributeValues.attribute')),避免N+1查询问题。

内容的提问来源于stack exchange,提问作者Родион Поляков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:15:47