
本文介绍一种简洁、可扩展的递归方法,替代深度不确定的多层 foreach 嵌套,自动按节点 depth 分组收集 tid,适用于任意深度的树形对象结构。
本文介绍一种简洁、可扩展的递归方法,替代深度不确定的多层 foreach 嵌套,自动按节点 depth 分组收集 tid,适用于任意深度的树形对象结构。
在处理动态深度的树形数据(如分类树、菜单树或组织架构)时,硬编码多层 foreach 不仅冗长难维护,更无法应对运行时未知的嵌套层级。原始代码通过 5 层嵌套勉强覆盖部分场景,但一旦新增层级即失效,且逻辑重复、易出错。
理想的解决方案是递归遍历 + 引用传参:定义一个递归函数,对每个节点执行“收集当前 tid → 递归处理 children”两个动作,天然适配任意深度。
以下是优化后的专业实现:
/**
* 递归收集树节点,按 depth 分组 tid
* @param array|object $item 当前层级节点(支持数组或单个对象)
* @param array &$data 引用传递的结果容器,格式为 [$depth => [$tid, ...]]
* @return void
*/
function collectTermsByDepth($item, &$data) {
// 安全校验:空值、非对象/数组跳过
if (empty($item)) {
return;
}
// 统一处理:若 $item 是单个对象(非数组),则转为单元素数组便于统一遍历
$items = is_array($item) ? $item : [$item];
foreach ($items as $node) {
// 确保是对象且含有 depth 和 tid 属性
if (!is_object($node) || !isset($node->depth) || !isset($node->tid)) {
continue;
}
// 按 depth 归类 tid
$depth = (int)$node->depth;
$data[$depth][] = $node->tid;
// 递归处理子节点(children 可能为 null、空数组或对象数组)
if (isset($node->children) && !empty($node->children)) {
collectTermsByDepth($node->children, $data);
}
}
}
/**
* 入口函数:封装递归调用,返回标准化结果
* @param array|object $tree 根节点(数组或单个对象)
* @return array 按 depth 索引的 tid 数组二维结构
*/
function buildTermDepthMap($tree) {
$result = [];
collectTermsByDepth($tree, $result);
ksort($result); // 可选:按 depth 升序排列键
return $result;
}
✅ 使用示例:
// 假设 $tree 是你的原始树形数据(数组或对象) $termMap = buildTermDepthMap($tree); print_r($termMap); // 输出结构与预期完全一致:[0]=>[20011,19991,...], [1]=>[...], ...
⚠️ 关键注意事项:
- 引用传参不可省略:&$data 确保所有递归层级操作同一数组,避免复制开销与逻辑断裂;
- 类型兼容性:函数自动适配 $tree 为数组(多根)或单对象(单根),提升复用性;
- 健壮性防护:显式检查 empty()、is_object()、属性存在性,防止 Notice 或 Warning;
- depth 类型转换:强制 (int) 避免字符串 key(如 '0' 与 0 混淆),保证数组索引一致性;
- children 空值处理:isset() && !empty() 双重判断,兼容 null、[]、false 等边界情况。
该方案彻底解耦层级逻辑,时间复杂度 O(n)(n 为总节点数),空间复杂度 O(d)(d 为最大深度,由递归栈决定),兼顾性能、可读性与工程健壮性,是处理动态树结构的标准实践。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











