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

如何使用mysqli和PHP按类别分组获取关联食谱数据?

解决分类分组的JSON格式问题

看起来你遇到的核心问题是:当前的JOIN查询会返回每条产品对应一条记录,直接转JSON就会生成重复的分类条目。我们可以通过两种常用方式实现按类别分组的目标格式,下面分别说明:

方法一:PHP端手动分组查询结果(推荐,易维护)

这种方式先获取所有关联数据,再通过PHP遍历将同一分类的产品聚合到一起,逻辑清晰且容易调整:

步骤1:执行查询并获取结果

保留你的JOIN查询(可以精简下字段只保留需要的内容):

// 调整查询,只获取必要字段
$query = "SELECT 
            c.id AS category_id, 
            c.category_name, 
            p.id AS recipe_id, 
            p.recipe_name 
          FROM " . $this->table_name . " p 
          LEFT JOIN categories c ON p.category_id = c.id";

// 执行查询(这里假设你的数据库连接是$this->db,根据实际情况调整)
$result = $this->db->query($query);
$rawData = $result->fetch_all(MYSQLI_ASSOC);

步骤2:遍历结果进行分组

初始化目标结构,然后把同一分类的产品归到对应的recipes数组中:

// 初始化最终要输出的JSON结构
$finalResponse = [
    "data" => [
        "menu" => []
    ],
    "status" => "1",
    "message" => ""
];

// 用分类ID作为临时键,避免重复创建分类条目
$categoryMap = [];

foreach ($rawData as $item) {
    $catId = $item['category_id'];
    
    // 如果该分类还未加入临时映射,先创建分类基础信息
    if (!isset($categoryMap[$catId])) {
        $categoryMap[$catId] = [
            "id" => md5($catId), // 对应你示例中的哈希ID,可根据需求替换生成方式
            "category_name" => $item['category_name'],
            "recipes" => []
        ];
    }
    
    // 将当前产品添加到对应分类的recipes数组
    $categoryMap[$catId]['recipes'][] = [
        "id" => $item['recipe_id'],
        "recipe_name" => $item['recipe_name']
    ];
}

// 把分类映射转成索引数组,放入menu中
$finalResponse['data']['menu'] = array_values($categoryMap);

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

方法二:SQL结合GROUP_CONCAT实现分组

这种方式在SQL层面将每个分类下的产品合并为JSON字符串,再在PHP中解析:

步骤1:修改查询语句

利用MySQL的JSON_OBJECT和GROUP_CONCAT函数聚合产品数据:

SELECT 
    c.id AS category_id,
    c.category_name,
    GROUP_CONCAT(
        JSON_OBJECT(
            'id', p.id,
            'recipe_name', p.recipe_name
        ) SEPARATOR ','
    ) AS recipes_json
FROM products p
LEFT JOIN categories c ON p.category_id = c.id
GROUP BY c.id, c.category_name;

步骤2:PHP解析结果并生成目标JSON

$query = "SELECT 
            c.id AS category_id,
            c.category_name,
            GROUP_CONCAT(
                JSON_OBJECT(
                    'id', p.id,
                    'recipe_name', p.recipe_name
                ) SEPARATOR ','
            ) AS recipes_json
          FROM products p
          LEFT JOIN categories c ON p.category_id = c.id
          GROUP BY c.id, c.category_name";

$result = $this->db->query($query);
$rawData = $result->fetch_all(MYSQLI_ASSOC);

$finalResponse = [
    "data" => [
        "menu" => []
    ],
    "status" => "1",
    "message" => ""
];

foreach ($rawData as $item) {
    // 将拼接的JSON字符串转为数组,处理空值情况
    $recipes = !empty($item['recipes_json']) ? json_decode('[' . $item['recipes_json'] . ']', true) : [];
    
    $finalResponse['data']['menu'][] = [
        "id" => md5($item['category_id']),
        "category_name" => $item['category_name'],
        "recipes" => $recipes
    ];
}

echo json_encode($finalResponse, JSON_PRETTY_PRINT);

注意事项

  • 你的categories表用utf8编码,products表用latin1,建议统一编码(比如都改成utf8mb4),避免出现乱码问题。
  • 使用GROUP_CONCAT时,默认有长度限制(默认1024字节),如果产品数量较多,需要先执行SET group_concat_max_len = 102400;调整长度。

内容的提问来源于stack exchange,提问作者Chitra Nandpal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:57:26