Kalnoy\Nestedset 是一個用於處理樹狀結構資料的 Laravel 套件,它實作了「嵌套集合模型(Nested Set Model)」,適合儲存與操作如分類目錄、組織架構等階層資料。
Kalnoy\Nestedset
高效能的樹狀結構儲存: 使用 Nested Set 模型來儲存節點位置,可在 O(1) 時間內查詢整棵樹或子樹,避免多層級 JOIN 操作。
簡單的 API 操作: 提供如 appendNode()、makeChildOf()、children() 等常用方法,讓操作如同使用一般 Eloquent 模型一樣方便。
appendNode()
makeChildOf()
children()
支援樹的遍歷與子樹操作: 可輕鬆遍歷整棵樹、查詢所有後代或子節點。
支援節點動態調整: 節點可自由移動至樹的其他位置,套件會自動處理相關索引調整。
資料庫索引效能佳: lft 和 rgt 欄位(由 ->nestedSet() 自動建立)支援快速查詢。
lft
rgt
->nestedSet()
支援 Laravel Eloquent ORM: 與原生 Eloquent 完美整合,易於上手。
自動同步 left/right 欄位: 插入、移動節點時自動處理索引更新,減少人工操作錯誤。
寫入操作相對複雜: 插入、刪除或移動節點時需調整多筆資料的索引,寫入成本高。
需要額外欄位: 除了基本欄位外,還需 lft、rgt(和 parent_id, depth)來表示樹結構。
parent_id
depth
不適合頻繁變動的樹: 若節點變動頻繁,每次都需重新計算索引,對效能影響大。
高並發下競爭風險: 多人同時異動節點位置,可能會產生資料不一致問題,需透過鎖定機制控制。
重建樹結構成本高: 當樹結構毀損時,可能需要重新建構整棵樹,代價不小。
不適合扁平資料結構: 若樹只有 1~2 層,Nested Set 的設計反而會造成過度設計。
電子產品 ├── 手機 │ ├── 智能手機 │ │ ├── Apple │ │ └── Samsung │ └── 功能手機 ├── 電腦 │ ├── 桌面電腦 │ └── 筆記型電腦 家電 ├── 冰箱 └── 洗衣機
Schema::create('categories', function (Blueprint $table) { $table->id(); $table->string('name'); $table->nestedSet(); // 建立 lft, rgt, parent_id, depth 欄位 $table->timestamps(); });
use Kalnoy\Nestedset\NodeTrait; class Category extends Model { use NodeTrait; }
use App\Models\Category; // 建立根節點 $electronics = Category::create(['name' => '電子產品']); $homeAppliances = Category::create(['name' => '家電']); // 建立第二層 $mobile = Category::create(['name' => '手機']); $computer = Category::create(['name' => '電腦']); $fridge = Category::create(['name' => '冰箱']); $washingMachine = Category::create(['name' => '洗衣機']); $electronics->appendNode($mobile); $electronics->appendNode($computer); $homeAppliances->appendNode($fridge); $homeAppliances->appendNode($washingMachine); // 建立第三層 $smartphones = Category::create(['name' => '智能手機']); $featurePhones = Category::create(['name' => '功能手機']); $desktop = Category::create(['name' => '桌面電腦']); $laptop = Category::create(['name' => '筆記型電腦']); $mobile->appendNode($smartphones); $mobile->appendNode($featurePhones); $computer->appendNode($desktop); $computer->appendNode($laptop); // 第四層品牌 $apple = Category::create(['name' => 'Apple']); $samsung = Category::create(['name' => 'Samsung']); $smartphones->appendNode($apple); $smartphones->appendNode($samsung);
// 查詢電子產品所有後代(含自己) $electronics = Category::where('name', '電子產品')->first(); $tree = $electronics->descendantsAndSelf; // 查詢子分類(不含自己) $mobile = Category::where('name', '手機')->first(); $children = $mobile->children; // 查詢 Apple 的父節點 $apple = Category::where('name', 'Apple')->first(); $parent = $apple->parent; // 將 Apple 移動到 功能手機 下 $featurePhones = Category::where('name', '功能手機')->first(); $apple->makeChildOf($featurePhones);
總經理 ├── 行銷部門 │ ├── 社群行銷 │ └── 搜索行銷 ├── 技術部門 │ ├── 前端團隊 │ └── 後端團隊 └── 人事部門
評論 1 ├── 回應 1.1 │ └── 回應 1.1.1 ├── 回應 1.2 評論 2
首頁 ├── 產品 │ ├── A │ ├── B ├── 服務 │ ├── A │ └── B └── 關於我們
管理員 ├── 主管 │ ├── 部門主管 │ └── 團隊主管 └── 員工
Kalnoy Nestedset(處理樹狀結構資料)
Kalnoy\Nestedset 套件介紹
Kalnoy\Nestedset是一個用於處理樹狀結構資料的 Laravel 套件,它實作了「嵌套集合模型(Nested Set Model)」,適合儲存與操作如分類目錄、組織架構等階層資料。優點
高效能的樹狀結構儲存:
使用 Nested Set 模型來儲存節點位置,可在 O(1) 時間內查詢整棵樹或子樹,避免多層級 JOIN 操作。
簡單的 API 操作:
提供如
appendNode()、makeChildOf()、children()等常用方法,讓操作如同使用一般 Eloquent 模型一樣方便。支援樹的遍歷與子樹操作:
可輕鬆遍歷整棵樹、查詢所有後代或子節點。
支援節點動態調整:
節點可自由移動至樹的其他位置,套件會自動處理相關索引調整。
資料庫索引效能佳:
lft和rgt欄位(由->nestedSet()自動建立)支援快速查詢。支援 Laravel Eloquent ORM:
與原生 Eloquent 完美整合,易於上手。
自動同步 left/right 欄位:
插入、移動節點時自動處理索引更新,減少人工操作錯誤。
缺點
寫入操作相對複雜:
插入、刪除或移動節點時需調整多筆資料的索引,寫入成本高。
需要額外欄位:
除了基本欄位外,還需
lft、rgt(和parent_id,depth)來表示樹結構。不適合頻繁變動的樹:
若節點變動頻繁,每次都需重新計算索引,對效能影響大。
高並發下競爭風險:
多人同時異動節點位置,可能會產生資料不一致問題,需透過鎖定機制控制。
重建樹結構成本高:
當樹結構毀損時,可能需要重新建構整棵樹,代價不小。
不適合扁平資料結構:
若樹只有 1~2 層,Nested Set 的設計反而會造成過度設計。
樹結構範例(商品分類)
資料庫結構
Schema::create('categories', function (Blueprint $table) { $table->id(); $table->string('name'); $table->nestedSet(); // 建立 lft, rgt, parent_id, depth 欄位 $table->timestamps(); });模型設定
use Kalnoy\Nestedset\NodeTrait; class Category extends Model { use NodeTrait; }初始化資料
use App\Models\Category; // 建立根節點 $electronics = Category::create(['name' => '電子產品']); $homeAppliances = Category::create(['name' => '家電']); // 建立第二層 $mobile = Category::create(['name' => '手機']); $computer = Category::create(['name' => '電腦']); $fridge = Category::create(['name' => '冰箱']); $washingMachine = Category::create(['name' => '洗衣機']); $electronics->appendNode($mobile); $electronics->appendNode($computer); $homeAppliances->appendNode($fridge); $homeAppliances->appendNode($washingMachine); // 建立第三層 $smartphones = Category::create(['name' => '智能手機']); $featurePhones = Category::create(['name' => '功能手機']); $desktop = Category::create(['name' => '桌面電腦']); $laptop = Category::create(['name' => '筆記型電腦']); $mobile->appendNode($smartphones); $mobile->appendNode($featurePhones); $computer->appendNode($desktop); $computer->appendNode($laptop); // 第四層品牌 $apple = Category::create(['name' => 'Apple']); $samsung = Category::create(['name' => 'Samsung']); $smartphones->appendNode($apple); $smartphones->appendNode($samsung);查詢範例
// 查詢電子產品所有後代(含自己) $electronics = Category::where('name', '電子產品')->first(); $tree = $electronics->descendantsAndSelf; // 查詢子分類(不含自己) $mobile = Category::where('name', '手機')->first(); $children = $mobile->children; // 查詢 Apple 的父節點 $apple = Category::where('name', 'Apple')->first(); $parent = $apple->parent; // 將 Apple 移動到 功能手機 下 $featurePhones = Category::where('name', '功能手機')->first(); $apple->makeChildOf($featurePhones);常見應用場景
公司組織架構
評論系統(階層式)
網站選單
權限階層設定
官方連結與文件