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

PHP 遞迴生成樹狀結構完整實作

     編輯:PHP 相關知識

應用場景

無限分類、選單導航、組織架構、評論回覆等層級不固定的資料結構,常以「遞迴」或「引用陣列」兩種方式輸出樹狀 HTML。

資料表設計

CREATE TABLE `tree` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `name` VARCHAR(100) NOT NULL,
    `parent` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '父節點 ID,0 為頂層',
    `ischild` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否有子節點',
    `sort` INT UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

遞迴輸出完整程式碼

<?php
header('Content-Type: text/html; charset=utf-8');

$pdo = new PDO('mysql:host=localhost;dbname=wz;charset=utf8', 'root', '123456');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/**
 * 遞迴輸出節點
 * @param PDO $pdo
 * @param int $parentId
 * @param int $level 階層深度,用於縮排
 */
function renderTree($pdo, $parentId = 0, $level = 0) {
    $stmt = $pdo->prepare('SELECT id, name, ischild FROM tree WHERE parent = ? ORDER BY sort, id');
    $stmt->execute([$parentId]);
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if (!$rows) return;

    $indent = str_repeat('    ', $level);

    foreach ($rows as $row) {
        $id = $row['id'];
        $name = htmlspecialchars($row['name']);
        $hasChild = (bool)$row['ischild'];

        // 展開/收合連結
        $toggle = $hasChild
            ? "[+] "
            : '- ';

        echo "
{$indent}{$toggle}{$name}
\n"; if ($hasChild) { // 子節點預設隱藏 echo "\n"; } } } // 輸出頂層節點 renderTree($pdo); ?> <script> function toggleNode(nodeId) { const childId = nodeId.replace('node_', 'child_'); const childDiv = document.getElementById(childId); const link = document.querySelector(`#${nodeId} a`); if (!childDiv) return; if (childDiv.style.display === 'none') { childDiv.style.display = 'block'; link.textContent = '[-]'; } else { childDiv.style.display = 'none'; link.textContent = '[+]'; } } </script> <style> .tree-node { cursor: pointer; } .tree-children { margin-left: 1.5em; } </style>

效能優化建議

  • 單次查詢 + 陣列組裝:資料量大時,先 SELECT id, name, parent FROM tree 全部撈出,PHP 端用引用陣列組裝樹,避免 N+1 查詢。
  • 快取樹狀 HTML:分類變動不頻繁時,將渲染結果存入 Redis / 檔案快取。
  • 前端虛擬滾動:節點超過千層時,配合 Vue/React 虛擬清單渲染。

非遞迴寫法(參考)

function buildTreeArray($rows) {
    $tree = [];
    $ref = [];

    foreach ($rows as $row) {
        $id = $row['id'];
        $ref[$id] = &$row;
        $row['children'] = [];
    }

    foreach ($rows as $row) {
        $pid = $row['parent'];
        if ($pid == 0 || !isset($ref[$pid])) {
            $tree[] = &$row;
        } else {
            $ref[$pid]['children'][] = &$row;
        }
    }
    return $tree;
}

此法只需一次查詢,適合大資料集,再配合模板引擎遞迴輸出 HTML。

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