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

PHP 實作無限遞迴分類選單:ThinkPHP 實戰範例

     編輯:PHP 綜合知識

ThinkPHP 社群常討論無限分類實作,許多教學採用「路徑法(0-1-2-3)」或「層級法」。本文分享一種以遞迴實作的簡潔做法,程式碼不超過 20 行,邏輯清晰易維護。

資料表結構

單表 channel 即可支援無限分層:

欄位說明
cid主鍵 ID
fatherid父分類識別(頂層為 NULL)
name分類名稱

註:頂層分類的 fatherid 設為 NULL 而非 0,配合外鍵關聯模型設計。

核心遞迴程式碼

class CategoryAction extends Action {
    // 類屬性:儲存遞迴結果
    public $tree = null;

    // 測試輸出
    public function test() {
        // 取得所有頂層分類
        $res = M('channel')->where('fatherid IS NULL')->select();
        $this->createtree($res);
        dump($this->tree);
    }

    // 遞迴方法
    private function createtree(array $data = null, $lv = 1) {
        for ($i = 0; $i < count($data); $i++) {
            // 寫入層級
            $data[$i]['lv'] = $lv;
            // 將當前記錄加入結果陣列末尾
            $this->tree[count($this->tree)] = $data[$i];
            // 查詢子分類
            $res = M('channel')->where('fatherid=' . $data[$i]['cid'])->select();
            // 遞迴處理子分類
            $this->createtree($res, $lv + 1);
        }
    }
}

邏輯解析

  1. 先查詢所有 fatherid IS NULL 的頂層分類。
  2. 進入遞迴函式,為每筆資料標記層級 lv。
  3. 將該筆資料推入 $this->tree 陣列末尾(保證父分類在子分類之前)。
  4. 查詢該分類下的子分類,若有結果則遞迴呼叫自身,層級 +1。
  5. for 迴圈若查無子分類($res 為空),自然結束遞迴,無需額外判斷。

效能考量與優化

實務上分類數量極少超過 200 筆,遞迴查詢效能足夠。若極度在意效能,可採用快取機制(如 Redis、檔案快取),分類異動時更新快取,讀取時直接取用,避免重複查詢。

排序支援

若需自訂分類順序,直接在 select() 前加上 order('sort_field ASC'),不影響遞迴邏輯。

原文出處:尛雷博客

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