1 回答

TA贡献1936条经验 获得超6个赞
應該是不用這麼複雜~
用遞歸可以很簡單達成這樣任務:
遞歸
function parseTree($tree, $root = null) {
$nested = array();
foreach($tree as $index => $child) {
if($child['pid'] == $root) {
unset($tree[$index]);
$child['children'] = parseTree($tree, $child['id']);
$nested[] = $child;
}
}
return empty($nested) ? null : $nested;
}
迭代
function parseTree($rows) {
// php >= 5.5 提供的方法,可以指定數組中對象的值當作 key 並返回一個新的數組
// 詳細用法可以看官方文檔,這裡簡略解釋下
// 這邊是以 id 來當做 key, 中間參數 null 指返回整個數組
$rows = array_column ( $rows, null, 'id' );
// 遍歷之
foreach ( $rows as $key => $val ) {
// 這時的 $key 會是 id
// 如果 pid 不為 false, 這邊 0 = false
if ( $val ['pid'] ) {
// 檢查 pid 指向的值是否存在
// 這裡就是上面為何要用 array_column 把 id 當 key 的理由
// 可以很快速的找到目標,不用再用各種方法來匹配對象
if ( isset ( $rows [$val ['pid']] )) {
// 存在的話就把 自己的 "參考" 往父元素的 children 裡面塞
// $rows [$key] 代表目前的元素
// $rows [$val ['pid']]['children'] 代表父元素的 children 數組
// 為何要傳參考,因為參考指向的是內存位置,這樣當你之後對著
// $rows [$key] 做變動時,所有參考$rows [$key]都會存取到相同的值
// 而 foreach 是傳值給 $val ,所以我們得手動加個 & 來指向正確的位址
$rows [$val ['pid']]['children'][] = &$rows [$key];
}
}
}
// 這裡是清除掉所有不是祖先元素 ( pid != 0)
// 因為該放進 children 的在上面的 foreach 中已經全部處理好了
// 所以這邊就直接 unset 不是祖先元素的,而 unset ( $rows [$key] ) 只是單純把這個數組的索引
// 給清除掉
// 不會清除掉之前 &$rows [$key] 所引用的參考,這涉及到 php gc 的原理,這邊只能先大概這麼講
foreach ( $rows as $key => $val ) {
if ( $val ['pid'] ) unset ( $rows [$key] );
}
return $rows;
}
添加回答
举报