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

PHP + MySQL 無限級分類完整實作(遞歸 + 效能優化討論)

     編輯:PHP 相關知識

前言

無限級分類是電商、CMS 核心功能。本文提供基於遞歸的完整實作:資料表結構、SQL 測試資料、MVC 風格單檔案展示(列表、新增、編輯、刪除、樹狀顯示、下拉選單),並討論遞歸效能瓶頸與優化方向。

資料表結構

CREATE TABLE `class` (
    `id` int(10) NOT NULL AUTO_INCREMENT,
    `name` varchar(250) CHARACTER SET utf8 DEFAULT NULL,
    `classid` int(10) DEFAULT NULL,  -- 父級 ID
    `sort` int(10) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

測試資料

INSERT INTO `class` (`id`, `name`, `classid`, `sort`) VALUES
(1, '中國', 0, 1),
(2, '廣西', 1, 1),
(3, '桂林', 2, 2),
(4, '廣東', 1, 2),
(5, '北京', 1, 3),
(6, '東莞', 4, 10),
(7, '南寧', 2, 10),
(8, '陽朔', 3, 10),
(9, '柳州', 2, 10),
(10, '廣州', 4, 10);

核心遞歸函數

樹狀列表顯示

function infinite_arr($margin, $pid) {
    global $class_arr;
    $prefix = str_repeat(' ', $margin * 4) . '|----';
    foreach ($class_arr as $item) {
        if ($item[2] == $pid) {
            echo "<tr><td>$prefix{$item[1]}</td><td>{$item[3]}</td>";
            echo "<td><a href='?action=edit&id={$item[0]}'>修改</a> | ";
            echo "<a href='?action=del&id={$item[0]}'>刪除</a></td></tr>";
            infinite_arr($margin + 1, $item[0]);
        }
    }
}

下拉選單生成

function infinite_select($margin, $pid, $selectedId) {
    global $class_arr;
    $prefix = str_repeat(' ', $margin * 4) . '|----';
    foreach ($class_arr as $item) {
        if ($item[2] == $pid) {
            $sel = ($item[0] == $selectedId) ? ' selected' : '';
            echo "<option value='{$item[0]}'$sel>$prefix{$item[1]}</option>";
            infinite_select($margin + 1, $item[0], $selectedId);
        }
    }
}

完整單檔案 MVC 示範

<?php
$mysql = new MySQL_Class('localhost', 'root', '');
$mysql->select_db('test');

$class_arr = array();
$sql = "SELECT * FROM `class` ORDER BY `sort` ASC, `id` DESC";
$query = $mysql->query($sql);
while ($row = $mysql->fetch_array($query)) {
    $class_arr[] = array($row['id'], $row['name'], $row['classid'], $row['sort']);
}

// 動作分發
switch ($_GET['action']) {
    case 'add':     // 顯示新增表單(含下拉選父級)
    case 'act_add': // 處理新增 POST
    case 'edit':    // 顯示編輯表單
    case 'act_edit':// 處理編輯 POST(防自我為父級)
    case 'del':     // 處理刪除
    case '': default: // 顯示樹狀列表
}
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>無限級分類</title></head><body>
<h2>分類列表</h2>
<a href="?action=add">添加分類</a>
<table><thead><tr><th>分類名稱</th><th>排序</th><th>操作</th></tr></thead><tbody>
<?php infinite_arr(0, 0); ?>
</tbody></table>
</body></html>

遞歸效能瓶頸與優化方向

問題原因優化方案
大量資料時極慢每次遞歸掃描全陣列 O(n²)建立 pid => children 索引陣列,O(n) 單次遍歷
深層遞歸爆棧PHP 預設堆疊限制改用迭代法(堆疊/佇列模擬)
頻繁查詢 DB每次操作重新 SELECT 全表引入緩存(Redis/Memcached)、資料庫層面支援(Nested Sets / Closure Table)

資料庫層面優化模式

  • Nested Sets(巢狀集合):lft/rgt 值,單查詢取得整棵子樹,移動節點代價大。
  • Closure Table(閉包表):單獨表儲存所有祖先-後代關係,查詢/移動/刪除均高效,現代首選。
  • 遞歸 CTE (MySQL 8.0+):WITH RECURSIVE 原生支援,無需額外欄位。

總結

遞歸實現無限分類邏輯清晰、代碼簡短,適合中小資料量(< 1000 條)。大型專案建議採用 **Closure Table + 緩存** 架構,資料庫層面解決樹狀查詢效能,應用層僅處理展示邏輯。理解遞歸與資料庫模式的權衡,是架構師必備能力。

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