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

PHP+MySQL 無限分類完整實作(含增刪改移)

     編輯:PHP 相關知識

PHP 無限分類系統完整教學

本文提供一套完整的 PHP + MySQL 無限分類實作程式碼,包含資料表結構、核心類別、前端操作介面(新增、編輯、刪除、移動),適合內容管理系統、電商分類、文章分類等場景。採用遞迴樹狀結構儲存,支援無限層級巢狀分類。

資料庫表結構

CREATE TABLE `p_newsclass` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `f_id` int(11) NOT NULL DEFAULT '0' COMMENT '父分類ID,0為頂層',
  `name` varchar(100) NOT NULL COMMENT '分類名稱',
  `addtime` datetime DEFAULT NULL COMMENT '建立時間',
  PRIMARY KEY (`id`),
  KEY `f_id` (`f_id`)
) ENGINE=MyISAM DEFAULT CHARSET=gbk;

核心類別:sortclass

採用陣列模擬樹狀結構,載入所有分類到記憶體,提供豐富的樹狀操作方法。

class sortclass {
    var $data = array();      // id => name 映射
    var $child = array(-1 => array()); // parent_id => 子分類ID陣列
    var $layer = array(-1 => -1);      // id => 層級深度
    var $parent = array();             // id => parent_id
    var $link;                         // 資料庫連線資源
    var $table;                        // 資料表名稱

    function __construct($link, $table) {
        $this->setnode(0, -1, '頂極節點');
        $this->link = $link;
        $this->table = $table;
        
        $results = mysql_query("SELECT * FROM $this->table", $this->link);
        while($node = mysql_fetch_array($results)) {
            $this->setnode($node['id'], $node['f_id'], $node['name']);
        }
    }

    // 設定節點資訊
    function setnode($id, $parent, $value) {
        $parent = $parent ? $parent : 0;
        $this->data[$id] = $value;
        $this->child[$id] = array();
        $this->child[$parent][] = $id;
        $this->parent[$id] = $parent;
        $this->layer[$id] = !isset($this->layer[$parent]) ? 0 : $this->layer[$parent] + 1;
    }

    // 遞迴取得所有子孫分類ID(含自己)
    function getlist(&$tree, $root = 0) {
        foreach ($this->child[$root] as $key => $id) {
            $tree[] = $id;
            if ($this->child[$id]) $this->getlist($tree, $id);
        }
    }

    // 取得分類名稱
    function getvalue($id) { return $this->data[$id]; }

    // 取得層級深度
    function getlayer($id, $space = false) {
        return $space ? str_repeat($space, $this->layer[$id]) : $this->layer[$id];
    }

    // 取得父分類ID
    function getparent($id) { return $this->parent[$id]; }

    // 取得所有祖先分類(含自己)
    function getparents($id) {
        $parent = array();
        while ($this->parent[$id] != -1) {
            $parent[] = $this->parent[$id];
            $id = $this->parent[$id];
        }
        ksort($parent);
        return $parent;
    }

    // 取得直接子分類
    function getchild($id) { return $this->child[$id]; }

    // 取得所有子孫分類(含自己)
    function getchilds($id = 0) {
        $child = array($id);
        $this->getlist($child, $id);
        return $child;
    }

    // 新增分類
    function addnode($name, $pid) {
        mysql_query("INSERT INTO $this->table (`f_id`,`name`) VALUES ('$pid','$name')", $this->link);
    }

    // 修改分類名稱
    function modnode($cid, $newname) {
        mysql_query("UPDATE $this->table SET `name`='$newname' WHERE `id` = $cid", $this->link);
    }

    // 刪除分類(含所有子孫)
    function delnode($cid) {
        $allchilds = $this->getchilds($cid);
        if (empty($allchilds)) {
            $sql = "DELETE FROM $this->table WHERE `id` = $cid";
        } else {
            $sql = 'DELETE FROM ' . $this->table . ' WHERE `id` IN (' . implode(',', $allchilds) . ',' . $cid . ')';
        }
        mysql_query($sql, $this->link);
    }

    // 移動分類(變更父分類)
    function movenode($cid, $topid) {
        mysql_query("UPDATE $this->table SET `f_id`=$topid WHERE `id` = $cid", $this->link);
    }
}

前端操作介面邏輯

// 資料庫連線
$link = mysql_connect('localhost', 'root', '') or die(mysql_error());
mysql_select_db('class', $link) or die(mysql_error());
mysql_query("SET NAMES gbk", $link);

// 實例化分類類別
$tree = new sortclass($link, '`p_newsclass`');

// 處理 POST/GET 操作
$op = !empty($_POST['op']) ? $_POST['op'] : $_GET['op'];

if (!empty($op)) {
    if ($op == 'add') {
        $tree->addnode($_POST['cname'], $_POST['pid']);
        redirect_back();
    }
    if ($op == 'mod') {
        $tree->modnode($_POST['cid'], $_POST['cname']);
        redirect_back();
    }
    if ($op == 'del') {
        $tree->delnode($_GET['cid']);
        redirect_back();
    }
    if ($op == 'move') {
        $tree->movenode($_POST['who'], $_POST['to']);
        redirect_back();
    }
}

// 取得完整分類樹(用於下拉選單等)
$category = $tree->getchilds();

// 生成巢狀下拉選單輔助函數
function makeselect($array, $formname) {
    global $tree;
    $select = '';
}

// 頁面跳轉輔助函數
function redirect_back() {
    echo '';
    exit;
}

HTML 表單範例(新增/編輯/移動)


分類名稱: 父分類:
分類名稱:
選擇要移動的分類: 移動到父分類:

效能優化建議

  • 大量資料時:改用「修改前序樹遍歷」或「閉包表」模型,避免遞迴查詢
  • 快取機制:將分類樹序列化快取至 Redis/Memcached/檔案,減少資料庫查詢
  • 資料庫索引:f_id 欄位務必建立索引
  • 現代化重寫:改用 PDO + Prepared Statements 防止 SQL 注入
  • 前端優化:搭配 jsTree、zTree 等 JS 庫實現拖曳排序、懶加載

常見問題 FAQ

Q: 刪除父分類時,子分類會怎麼樣?
A: 程式碼會遞迴刪除所有子孫分類(delnode 方法),請謹慎操作。
Q: 如何顯示麵包屑導航?
A: 使用 getparents($id) 取得祖先陣列,反序輸出即可。
Q: 支援排序功能嗎?
A: 目前程式碼無排序欄位,建議加入 sort_order 欄位並在查詢時 ORDER BY sort_order。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved