如何通过循环将子分类产品数量累加到各级父分类?
如何将子分类产品数量累加到父分类(含多级父分类)
需要把所有子分类(包括多级子分类)的产品数量,逐层累加到对应的父分类中,最终每个父分类的count值是自身产品数加上所有子分类的产品数总和。
核心思路
从最底层的分类(叶子节点)开始,逐层向上遍历父分类,将当前分类的产品数累加到每个父分类的count中,避免重复计算,确保所有子分类的数量都被正确汇总到上级分类。
方法一:筛选叶子节点后向上累加
先找出所有没有子分类的叶子节点,再逐个将它们的产品数向上传递到所有父分类。
代码示例
// 假设你的分类数组为 $categories(键为分类ID,值包含id、parent_id、count字段) $calculatedCategories = $categories; // 复制原数组,避免修改原始数据 // 1. 收集所有父分类ID的集合,用于判断是否为叶子节点 $parentIds = array_column($calculatedCategories, 'parent_id'); // 2. 筛选叶子节点:ID不在父ID集合中的分类(无任何子分类) $leafCategories = array_filter($calculatedCategories, function($category) use ($parentIds) { return !in_array($category['id'], $parentIds); }); // 3. 遍历叶子节点,向上累加产品数到所有父分类 foreach ($leafCategories as $leaf) { $currentParentId = $leaf['parent_id']; $countToAdd = $leaf['count']; // 循环向上查找父分类,直到顶级分类(parent_id为null) while ($currentParentId !== null && isset($calculatedCategories[$currentParentId])) { $calculatedCategories[$currentParentId]['count'] += $countToAdd; // 获取上一级父分类ID $currentParentId = $calculatedCategories[$currentParentId]['parent_id']; } } // 此时 $calculatedCategories 即为汇总后的分类数组
说明
- 复制原数组是为了保留原始数据,不需要的话可直接操作原数组。
array_column提取所有分类的parent_id,以此判断分类是否为叶子节点(无其他分类以它为父类)。- 通过
while循环向上遍历父分类链,确保每个叶子节点的产品数被所有上级父分类汇总。
方法二:按分类深度排序后累加
若担心叶子节点筛选出错,可先给所有分类按层级深度从深到浅排序,再遍历每个分类向上累加,确保子分类先于父类被处理。
代码示例
$calculatedCategories = $categories; $depthCache = []; // 缓存分类深度,提升计算效率 // 递归计算分类的层级深度 function getCategoryDepth($categoryId, $categories, &$depthCache) { if (isset($depthCache[$categoryId])) { return $depthCache[$categoryId]; } $category = $categories[$categoryId]; if ($category['parent_id'] === null) { return $depthCache[$categoryId] = 0; } // 当前分类深度 = 父分类深度 + 1 return $depthCache[$categoryId] = getCategoryDepth($category['parent_id'], $categories, $depthCache) + 1; } // 按分类深度降序排序(最深的分类排在最前面) usort($calculatedCategories, function($a, $b) use ($calculatedCategories, &$depthCache) { $depthA = getCategoryDepth($a['id'], $calculatedCategories, $depthCache); $depthB = getCategoryDepth($b['id'], $calculatedCategories, $depthCache); return $depthB - $depthA; }); // 遍历排序后的分类,向上累加产品数 foreach ($calculatedCategories as &$category) { $currentParentId = $category['parent_id']; while ($currentParentId !== null && isset($calculatedCategories[$currentParentId])) { $calculatedCategories[$currentParentId]['count'] += $category['count']; $currentParentId = $calculatedCategories[$currentParentId]['parent_id']; } } unset($category); // 释放引用,避免后续数组操作异常 // 汇总后的分类数组已保存在 $calculatedCategories 中
说明
getCategoryDepth通过递归计算分类深度,并用缓存避免重复计算,适合大规模分类数组。usort将分类按深度从深到浅排序,确保子分类的数量先被累加到父分类中,避免遗漏。
注意事项
- 确认分类数组中
parent_id对应的是分类的数组键(如示例中的1、2、21),而非数据库的id字段。 - 若产品属于多个分类,代码会正常累加每个分类的产品数到各自的父分类链中。
- 3000个分类的规模下,两种方法均可高效处理,方法一性能略优,方法二更适配复杂分类结构。
内容的提问来源于stack exchange,提问作者Rediska
相关产品推荐
相关产品推荐

