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

PHP 無限分類實戰:以 MySQL CONCAT 與路徑編碼構建樹狀結構

     編輯:PHP 綜合知識

無限分類是電商、CMS、後台管理系統的核心需求。本文採用「路徑編碼法」結合 MySQL CONCAT() 函數,單查詢即可取得完整層級關係,無需遞迴多次查詢,效能與簡潔度兼備。

一、資料表設計:catpath 儲存祖先鏈

核心欄位 catpath 以分隔符(如 -)串聯所有祖先 ID,根節點為 0:

CREATE TABLE `category` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `catpath` VARCHAR(255) DEFAULT NULL COMMENT '祖先路徑,如 0-1-3',
    `name` VARCHAR(255) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

範例資料:

INSERT INTO `category` VALUES
(1, '0', '網站首頁'),
(2, '0-1', 'Linux OS'),
(3, '0-1', 'Apache服務器'),
(4, '0-1', 'MySQL數據庫'),
(5, '0-1', 'PHP腳本語言'),
(6, '0-1-2', 'Linux 系統教程'),
(7, '0-1-2', 'Linux 網絡技術'),
(8, '0-1-2', 'Linux 安全基礎'),
(9, '0-1-2-7', 'Linux LAMP'),
(10, '0-1-3-10', 'apache Server');

分隔符可自訂(,、| 等),只需統一處理邏輯。

二、單一 SQL 取得完整層級與排序

利用 CONCAT(catpath, '-', id) 產生完整路徑 abspath,直接 ORDER BY abspath 即可獲得樹狀順序:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', 'root');
$sql = "SELECT id, CONCAT(catpath, '-', id) AS abspath, name
        FROM category
        ORDER BY abspath";
$stmt = $pdo->query($sql);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

三、PHP 產生縮排與下拉選單

根據路徑深度(分隔符計數)計算縮排層級:

<?php
$options = '';
foreach ($rows as $row) {
    $depth = substr_count($row['abspath'], '-'); // 0 為根
    $indent = str_repeat('    ', $depth);
    $options .= "<option value=\"{$row['id']}\">{$indent}{$row['name']}</option>";
}
echo "<select name=\"cat_id\">{$options}</select>";

輸出效果:

網站首頁
    Linux OS
        Linux 系統教程
        Linux 網絡技術
            Linux LAMP
        Linux 安全基礎
    Apache服務器
        apache Server
    MySQL數據庫
    PHP腳本語言

四、新增節點時的 catpath 計算

<?php
function buildCatpath(PDO $pdo, int $parentId): string {
    if ($parentId === 0) return '0';
    $stmt = $pdo->prepare("SELECT catpath FROM category WHERE id = ?");
    $stmt->execute([$parentId]);
    $parent = $stmt->fetchColumn();
    return $parent . '-' . $parentId;
}
// 使用範例
$newCatpath = buildCatpath($pdo, 2); // 0-1-2
$pdo->prepare("INSERT INTO category (catpath, name) VALUES (?, ?)")
    ->execute([$newCatpath, '新分類']);

五、優缺點總結與擴充建議

優點缺點
單查詢取全樹、排序自然catpath 長度受 VARCHAR 限制(極深層級可能溢位)
移動子樹只需更新該節點及後代 catpath大量移動時需批次更新,可配合觸發器或佇列
相容所有 MySQL 版本,無需 CTE/遞迴 CTE查詢特定深度需額外計算

若專案使用 MySQL 8.0+,可改用 WITH RECURSIVE CTE 方案,彈性更高;但路徑編碼法在舊版本與高讀取場景下依然極具競爭力。

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