Laravel中如何用Query Builder将MySQL查询结果转为多维数组
解决方案:用Query Builder查询并重组为多维数组
第一步:关联所有表查询出扁平数据
先通过join关联所有需要的表,查询出包含所有层级字段的扁平结果集:
$flatResults = DB::table('products') ->join('product_details', 'products.id', '=', 'product_details.product_id') ->join('subcategories', 'product_details.subcategory_id', '=', 'subcategories.id') ->join('product_attributes', 'product_details.id', '=', 'product_attributes.product_detail_id') ->join('sub_images', 'product_attributes.id', '=', 'sub_images.product_attribute_id') // 筛选活跃数据,可根据需求调整 ->where('subcategories.is_active', true) ->where('product_details.is_active', true) ->select( // 给每个字段加别名避免冲突 'products.id as product_id', 'products.name as product_name', 'products.description as product_description', 'subcategories.id as subcategory_id', 'subcategories.subcategory_name', 'product_details.id as detail_id', 'product_details.sku', 'product_details.price', 'product_attributes.id as attribute_id', 'product_attributes.size_id', 'product_attributes.color_id', 'product_attributes.material_id', 'product_attributes.brand_id', 'product_attributes.rating', 'sub_images.sub_image' ) ->get();
第二步:将扁平数据重组为多维数组
利用Laravel集合的groupBy和map方法,逐层嵌套分组,构建目标结构:
$structuredData = $flatResults->groupBy('product_id')->map(function ($productRecords) { // 取当前产品的基础信息(同组内基础信息一致) $baseProduct = $productRecords->first(); return [ 'id' => $baseProduct->product_id, 'name' => $baseProduct->product_name, 'description' => $baseProduct->product_description, 'subcategories' => $productRecords->groupBy('subcategory_id')->map(function ($subcatRecords) { $baseSubcat = $subcatRecords->first(); return [ 'id' => $baseSubcat->subcategory_id, 'subcategory_name' => $baseSubcat->subcategory_name, 'product_details' => $subcatRecords->groupBy('detail_id')->map(function ($detailRecords) { $baseDetail = $detailRecords->first(); return [ 'id' => $baseDetail->detail_id, 'sku' => $baseDetail->sku, 'price' => $baseDetail->price, 'product_attributes' => $detailRecords->groupBy('attribute_id')->map(function ($attrRecords) { $baseAttr = $attrRecords->first(); return [ 'id' => $baseAttr->attribute_id, 'size_id' => $baseAttr->size_id, 'color_id' => $baseAttr->color_id, 'material_id' => $baseAttr->material_id, 'brand_id' => $baseAttr->brand_id, 'rating' => $baseAttr->rating, // 提取当前属性下的所有图片 'sub_images' => $attrRecords->pluck('sub_image')->filter()->toArray() ]; })->values()->toArray(), // 重置数组键为连续索引 ]; })->values()->toArray(), ]; })->values()->toArray(), ]; })->values()->toArray();
关键说明
groupBy:按层级ID分组,将同层级的记录聚合到一起map:遍历分组后的集合,重组为需要的数组结构first():同组内的基础字段(如产品名称、分类名称)是一致的,取第一条即可pluck('sub_image'):提取当前属性下的所有图片URL,filter()可过滤空值values():重置数组键,避免用分组ID作为键,生成连续索引的数组
如果需要处理无关联数据的场景(比如某个产品属性没有图片),可以在对应层级添加判断,例如:
'sub_images' => $attrRecords->isNotEmpty() ? $attrRecords->pluck('sub_image')->filter()->toArray() : []
内容的提问来源于stack exchange,提问作者Rushi Bhatt
相关产品推荐
相关产品推荐

