在 PHP 開發中,處理樹狀結構數據(如商品分類、地區劃分、組織架構)是常見需求。本文將詳細講解如何使用遞歸算法實現無限級分類,並提供完整、可直接運行的代碼示例。
無限分類的本質是「父子關係」的鏈式結構。數據表通常包含 id(主鍵)、name(名稱)、pid(父級 ID)三個關鍵字段。根節點的 pid 為 0。遞歸函數的邏輯是:傳入父級 ID,查找所有子節點,對每個子節點再次調用自身,直到沒有子節點為止。
以下示例模擬地區數據,展示如何將一維數組轉換為帶有層級縮進的樹狀輸出,並返回排序後的列表:
<?php
// 模擬數據:地區分類
$area = array(
array('id'=>1, 'area'=>'北京', 'pid'=>0),
array('id'=>2, 'area'=>'廣西', 'pid'=>0),
array('id'=>3, 'area'=>'廣東', 'pid'=>0),
array('id'=>4, 'area'=>'福建', 'pid'=>0),
array('id'=>11, 'area'=>'朝陽區', 'pid'=>1),
array('id'=>12, 'area'=>'海澱區', 'pid'=>1),
array('id'=>21, 'area'=>'南寧市', 'pid'=>2),
array('id'=>45, 'area'=>'福州市', 'pid'=>4),
array('id'=>113, 'area'=>'亞運村', 'pid'=>11),
array('id'=>115, 'area'=>'奧運村', 'pid'=>11),
array('id'=>234, 'area'=>'武鳴縣', 'pid'=>21)
);
/**
* 遞歸構建無限分類
* @param array $arr 原始數據
* @param int $pid 父級 ID
* @param int $lev 當前層級(用於縮進顯示)
* @return array 排序後的列表
*/
function buildTree($arr, $pid = 0, $lev = 0) {
static $list = array(); // 靜態變量保存結果,避免重複傳遞
foreach ($arr as $v) {
if ($v['pid'] == $pid) {
// 輸出視覺效果:層級縮進
echo str_repeat(' ', $lev) . $v['area'] . '<br />';
$list[] = $v;
// 遞歸查找子節點
buildTree($arr, $v['id'], $lev + 1);
}
}
return $list;
}
// 執行並輸出結果
echo '<pre>';
$list = buildTree($area);
echo '<hr>';
print_r($list);
?>
$list:在函數內部聲明為 static,使其在遞歸調用間保持狀態,最終返回完整的排序列表。$lev:每次遞歸遞增,配合 str_repeat 實現視覺縮進,直觀展示層級關係。id 和 pid,且父節點需在子節點之前定義(或數據已按 ID 排序),否則可能遺漏節點。實際項目中,若數據量大(如超過萬條),遞歸遍歷整個數組會有性能瓶頸。推薦採用「引用賦值法」或「SQL 遞歸查詢(CTE)」預先構建樹形數組,或使用閉包表、物化路徑等數據庫設計模式。對於中小型項目,本文方法簡潔高效,完全足夠。