首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 多級樹狀選單:資料庫驅動的遞迴式摺疊導航

     編輯:PHP 綜合知識

系統設計

採用鄰接表模型在 MySQL 儲存選單結構,欄位包含:menu_id、menu(名稱)、menu_grade(層級 1=主選單)、menu_superior(父選單 ID)。透過遞迴函數 my_menu() 動態生成可摺疊的樹狀導航,支援無限層級。

資料表結構與範例資料

CREATE TABLE menu (
    menu_id INT(11) NOT NULL AUTO_INCREMENT,
    menu VARCHAR(20) NOT NULL,
    menu_grade INT(11) NOT NULL,
    menu_superior INT(11) NOT NULL,
    PRIMARY KEY (menu_id)
);

INSERT INTO menu VALUES
(1, '計算機', 1, 0),
(2, '編程', 2, 1),
(3, '網絡', 2, 1),
(4, 'PHP與MySql', 3, 2),
(5, 'C語言', 3, 2),
(6, '網頁制作', 3, 3),
(7, 'TCP、IP協議', 3, 3),
(8, '數學', 1, 0),
(9, '高等數學', 2, 8),
(10, '線性代數', 3, 9),
(11, '離散數學', 3, 9),
(12, '初等數學', 2, 8),
(13, '文學', 1, 0),
(14, '中國文學', 2, 13),
(15, 'php', 4, 4),
(16, 'mysql', 4, 4);

核心遞迴函數 my_menu()

function my_menu($menu_content, $i, $menu_grade_temp, $menu_superior_temp) {
    global $PHP_SELF;
    $temp1 = $menu_grade_temp + 1;
    $menu_superior_temp_array = explode("/", $menu_superior_temp);

    for ($t = 0; $t < $i; $t++) {
        $menu_array = explode("/", $menu_content[$t]);
        // 條件:層級符合 且 父ID符合當前路徑對應層級的父ID
        if (($menu_array[2] == $menu_grade_temp) && 
            ($menu_array[3] == $menu_superior_temp_array[$menu_grade_temp - 1])) {

            // 顯示層級縮排箭頭
            for ($p = 1; $p <= $menu_grade_temp; $p++) { echo ">"; }

            $temp3 = $menu_superior_temp_array;
            $temp3[$menu_grade_temp] = $menu_array[0];
            $temp2 = implode("/", $temp3);

            // 判斷是否為當前展開的分支
            if ($menu_array[0] == $menu_superior_temp_array[$temp1 - 1]) {
                $temp5 = $temp1 - 1;
                $temp3[$menu_grade_temp] = "";
                $temp6 = implode("/", $temp3);
                // 已展開:顯示「收合」連結,遞迴輸出子選單
                echo "<a href=\"" . $PHP_SELF . "?menu_grade_temp=" . $temp5 . "&menu_superior_temp=" . $temp6 . "\">" . htmlspecialchars($menu_array[1]) . "</a><br>";
                my_menu($menu_content, $i, $temp1, $temp2);
            } else {
                // 未展開:顯示「展開」連結
                $temp3[$menu_grade_temp + 1] = "";
                $temp6 = implode("/", $temp3);
                echo "<a href=\"" . $PHP_SELF . "?menu_grade_temp=" . $temp1 . "&menu_superior_temp=" . $temp6 . "\">" . htmlspecialchars($menu_array[1]) . "</a></br>";
            }
        }
    }
}

主程式流程

// 1. 連線資料庫
mysql_connect("localhost", "root", "zmxj");
mysql_select_db("joss");

// 2. 讀取所有選單,依層級排序
$query = "SELECT * FROM menu ORDER BY menu_grade";
$db_data = mysql_query($query);

$i = 0;
while (list($menu_id, $menu, $menu_grade, $menu_superior) = mysql_fetch_row($db_data)) {
    $menu_content[$i] = "$menu_id/$menu/$menu_grade/$menu_superior";
    $i++;
}

// 3. 初始化參數
if ($menu_grade_temp == "") { $menu_superior_temp = 0; }

// 4. 從第 1 層開始渲染
my_menu($menu_content, $i, 1, $menu_superior_temp);

運作機制解析

  • 狀態保存:透過 URL 參數 menu_grade_temp(目前層級)、menu_superior_temp(各層級對應的父 ID 串列,以 / 分隔)維持展開/收合狀態,無需 Session。
  • 遞迴終止條件:資料集中無符合層級與父 ID 的項目時,迴圈自然結束。
  • 縮排顯示:以 > 字元重複次數表示層級深度。

優缺點分析與現代化建議

維度現狀建議改進
資料結構鄰接表改用 Closure Table 或 Nested Set 支援高效率子樹查詢、移動、排序
前端呈現PHP 直輸 HTML + 超連結換頁改為 JSON API + 前端 Vue/React 組件,支援 AJAX 懶加載、動畫、鍵盤導航
狀態管理URL 參數前端狀態或 localStorage 記住展開狀態,刷新不重置
權限控制無加入 role_id 欄位,查詢時 JOIN 使用者權限表
效能全表撈入記憶體遞迴大型選單採用遞迴 CTE 或 Closure Table 分頁載入

現代化 API 範例

// GET /api/menu?parent=0
// 回傳 JSON
[
  {"id":1,"label":"計算機","grade":1,"parent":0,"children":[
    {"id":2,"label":"編程","grade":2,"parent":1,"children":[...]},
    {"id":3,"label":"網絡","grade":2,"parent":1,"children":[...]}
  ]},
  {"id":8,"label":"數學","grade":1,"parent":0,"children":[...]}
]

結語

這個經典範例展示了 PHP 早期「資料庫+遞迴函數+URL 狀態」構建動態導航的完整思路。雖然渲染方式屬於伺服器端直出時代,但樹狀資料的遞迴處理、狀態編碼、層級關聯邏輯,在現代前端組件庫的 Tree/Menu 實作中依然是核心演算法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved