无限分类实现 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 = [];
$stmt = $pdo->prepare("SELECT * FROM categories WHERE parent_id = ?");
$stmt->execute([$parentId]);
while ($row = $stmt->fetch()) {
$row['children'] = getChildren($row['id']);
$categories[] = $row;
}
return $categories;
}
路径枚举模式(Path Enumeration)
在记录中存储从根节点到当前节点的完整路径。

CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
path VARCHAR(255) NOT NULL COMMENT '如1/2/3'
);
查询子分类:
function getChildren($path) {
$stmt = $pdo->prepare("SELECT * FROM categories WHERE path LIKE ? ORDER BY path");
$stmt->execute([$path . '%']);
return $stmt->fetchAll();
}
嵌套集模式(Nested Set)
使用左右值表示层级关系,查询效率高但更新复杂。
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
lft INT NOT NULL,
rgt INT NOT NULL
);
查询子树:

function getSubTree($nodeId) {
$stmt = $pdo->prepare("SELECT node.* FROM categories AS node,
categories AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND parent.id = ? ORDER BY node.lft");
$stmt->execute([$nodeId]);
return $stmt->fetchAll();
}
闭包表模式(Closure Table)
使用单独的关系表存储节点间的所有路径。
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE category_paths (
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 getDescendants($categoryId) {
$stmt = $pdo->prepare("SELECT c.* FROM categories c
JOIN category_paths cp ON c.id = cp.descendant
WHERE cp.ancestor = ?");
$stmt->execute([$categoryId]);
return $stmt->fetchAll();
}
性能比较
邻接列表:实现简单,但递归查询性能较差 路径枚举:查询简单,但路径维护复杂 嵌套集:查询高效,但更新操作复杂 闭包表:灵活性高,但需要额外存储空间
选择哪种实现方式取决于具体的应用场景和性能需求。对于中小型项目,邻接列表通常足够使用;对于大型复杂项目,闭包表或嵌套集可能更合适。





