無限級分類(多級分類)是電商、CMS、權限系統的基礎數據結構。核心思想:每條記錄擁有 id 與 pid(父級 ID),根節點 pid=0。本文提供兩種經典 PHP 實現:遞歸查詢輸出扁平列表(適合前端遞歸渲染)與 引用構建多維樹形數組(適合 API 直接輸出 JSON)。
public function getlist($pid = 0, &$result = [], $spac = 0) {
$spac += 2;
$list = M('liuyan')->where('pid=' . $pid)->select();
foreach ($list as $val) {
$val['content'] = str_repeat(' ', $spac) . $val['content']; // 視覺縮進
$result[] = $val;
$this->getlist($val['id'], $result, $spac); // 遞歸子節點
}
return $result;
}
function genTree($items, $id = 'id', $pid = 'pid', $son = 'children') {
$tree = []; // 格式化後的樹
$tmpMap = []; // 臨時扁平映射:id => 節點引用
// 1. 建立 id 映射
foreach ($items as $item) {
$tmpMap[$item[$id]] = $item;
}
// 2. 遍歷構建父子關係(利用引用 &)
foreach ($items as $item) {
if (isset($tmpMap[$item[$pid]])) {
// 父節點存在,將當前節點引用掛載到父節點的 children 數組
$tmpMap[$item[$pid]][$son][] = &$tmpMap[$item[$id]];
} else {
// 無父節點(pid=0 或父節點不在數據集),作為根節點
$tree[] = &$tmpMap[$item[$id]];
}
}
unset($tmpMap); // 釋放映射表
return $tree;
}
$items1 = [
['id'=>1, 'pid'=>0, 'name'=>'一級11'],
['id'=>11, 'pid'=>0, 'name'=>'一級12'],
['id'=>2, 'pid'=>1, 'name'=>'二級21'],
['id'=>10, 'pid'=>11, 'name'=>'二級22'],
['id'=>3, 'pid'=>1, 'name'=>'二級23'],
// ... 更多層級
];
var_dump(genTree($items1));
輸出將呈現巢狀結構:
array(
0 => array('id'=>1, 'pid'=>0, 'name'=>'一級11', 'children'=>array(
0 => array('id'=>2, 'pid'=>1, 'name'=>'二級21', 'children'=>array(...)),
1 => array('id'=>3, 'pid'=>1, 'name'=>'二級23'),
...
)),
1 => array('id'=>11, 'pid'=>0, 'name'=>'一級12', 'children'=>array(...))
)
| 維度 | 遞歸查庫 (方案一) | 單查+引用構樹 (方案二) |
|---|---|---|
| 查詢次數 | O(節點數) | 1 次 |
| 時間複雜度 | O(N log N) ~ O(N²) | O(N) |
| 內存佔用 | 低(流式處理) | 中(需載入全量數據) |
| 適用場景 | 數據量小、實時性要求高、後台管理 | 數據量大、API 輸出、前端樹形組件 |
path (如 0,1,2,5) 或 depth,支持單條 SQL 查詢子樹、祖先鏈。掌握「單次查詢 + 引用構建樹」模式,是 PHP 處理層級數據的必備技能,亦是許多框架(Laravel nestedset、ThinkPHP Tree)底層實現的核心邏輯。