php 无限分类的实现
无限分类的实现方法
无限分类通常用于构建树形结构数据,如商品分类、多级菜单等。以下是几种常见的实现方式:
邻接列表模型(Adjacency List)
邻接列表是最简单的实现方式,通过在每个节点中存储父节点的ID来构建层级关系。
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
parent_id INT DEFAULT NULL,
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE CASCADE
);
查询所有子节点(递归方式):
function getChildren($parentId = 0) {
$categories = [];
$result = mysqli_query($conn, "SELECT * FROM categories WHERE parent_id = $parentId");
while ($row = mysqli_fetch_assoc($result)) {
$row['children'] = getChildren($row['id']);
$categories[] = $row;
}
return $categories;
}
嵌套集模型(Nested Set)
嵌套集模型通过left和right值来表示节点在树中的位置,查询效率高但更新复杂。
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
lft INT NOT NULL,
rgt INT NOT NULL
);
查询子树:
SELECT node.*
FROM categories AS node, categories AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND parent.id = 1
ORDER BY node.lft;
路径枚举(Path Enumeration)
通过存储从根节点到当前节点的完整路径来实现。
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
path VARCHAR(255) NOT NULL
);
查询子节点:
SELECT * FROM categories WHERE path LIKE '1/2/%';
闭包表(Closure Table)
使用单独的关联表存储节点之间的关系,是最灵活的实现方式。
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE category_closure (
ancestor INT NOT NULL,
descendant INT NOT NULL,
depth INT NOT NULL,
PRIMARY KEY (ancestor, descendant),
FOREIGN KEY (ancestor) REFERENCES categories(id),
FOREIGN KEY (descendant) REFERENCES categories(id)
);
查询所有后代节点:
SELECT c.*
FROM categories c
JOIN category_closure cc ON c.id = cc.descendant
WHERE cc.ancestor = 1 AND cc.descendant != 1;
性能比较
- 邻接列表:简单易用,但递归查询性能较差
- 嵌套集:查询性能好,但更新操作复杂
- 路径枚举:简单,但依赖字符串操作
- 闭包表:最灵活,查询和更新都方便,但需要额外表
实际应用建议
对于中小型项目,邻接列表或路径枚举足够简单实用。大型项目建议使用闭包表或嵌套集模型。现代框架如Laravel的Eloquent已内置对树形结构的支持,可简化开发。







