无限分类实现 php
无限分类的实现方法
无限分类通常用于组织结构化的层级数据,如商品分类、地区分类等。以下是几种常见的实现方式:
邻接表模型(Adjacency List)
邻接表是最简单的实现方式,通过在表中添加一个parent_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 getCategoryTree($parentId = 0, $level = 0) {
$categories = [];
$result = mysqli_query($conn, "SELECT * FROM categories WHERE parent_id = $parentId");
while ($row = mysqli_fetch_assoc($result)) {
$row['level'] = $level;
$categories[] = $row;
$categories = array_merge($categories, getCategoryTree($row['id'], $level + 1));
}
return $categories;
}
路径枚举法(Path Enumeration)
通过在表中添加一个path字段,存储从根节点到当前节点的完整路径。

CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
path VARCHAR(255) NOT NULL
);
// 添加分类
function addCategory($name, $parentId = 0) {
if ($parentId == 0) {
$path = '0';
} else {
$parent = mysqli_query($conn, "SELECT path FROM categories WHERE id = $parentId");
$path = mysqli_fetch_assoc($parent)['path'] . ',' . $parentId;
}
mysqli_query($conn, "INSERT INTO categories (name, path) VALUES ('$name', '$path')");
}
嵌套集模型(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
);
// 获取分类树
function getCategoryTree($parentId = 0) {
$result = mysqli_query($conn, "SELECT node.* FROM categories AS node, categories AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND parent.id = $parentId
ORDER BY node.lft");
return mysqli_fetch_all($result, MYSQLI_ASSOC);
}
闭包表(Closure Table)
使用单独的关联表存储节点之间的关系,适合频繁查询的场景。
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE category_relations (
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)
);
// 添加分类关系
function addCategoryRelation($ancestor, $descendant, $depth) {
mysqli_query($conn, "INSERT INTO category_relations (ancestor, descendant, depth)
VALUES ($ancestor, $descendant, $depth)");
}
性能比较
- 邻接表:简单易实现,但递归查询性能较差
- 路径枚举:查询方便,但维护路径复杂
- 嵌套集:查询高效,但插入和更新成本高
- 闭包表:查询和维护都较方便,但需要额外存储空间
选择哪种实现方式取决于具体应用场景和性能需求。对于中小型项目,邻接表或路径枚举通常足够;对于大型项目,可能需要考虑嵌套集或闭包表。






