php 实现无限分类
无限分类的实现方法
无限分类通常用于构建多级分类系统,如商品分类、文章分类等。以下是几种常见的实现方法:
邻接表模型(Adjacency List Model)
邻接表模型是最简单的实现方式,通过父ID字段来建立层级关系。每个记录存储一个指向其父记录的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 getChildCategories($parentId = 0, $level = 0) {
static $categories = [];
$query = "SELECT * FROM categories WHERE parent_id = " . (int)$parentId;
$result = mysqli_query($connection, $query);
while ($row = mysqli_fetch_assoc($result)) {
$row['level'] = $level;
$categories[] = $row;
getChildCategories($row['id'], $level + 1);
}
return $categories;
}
路径枚举模型(Path Enumeration Model)
这种方法通过存储从根节点到当前节点的完整路径来表示层级关系。
// 数据库表结构示例
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
path VARCHAR(255) NOT NULL COMMENT '如:1/2/3'
);
// 获取某个分类的所有子分类
function getChildCategories($categoryId) {
$query = "SELECT * FROM categories WHERE path LIKE '" . (int)$categoryId . "/%'";
$result = mysqli_query($connection, $query);
return mysqli_fetch_all($result, MYSQLI_ASSOC);
}
嵌套集模型(Nested Set Model)
嵌套集模型使用左右值来表示节点在树中的位置,查询效率高但更新复杂。

// 数据库表结构示例
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
lft INT NOT NULL,
rgt INT NOT NULL
);
// 获取某个节点的所有子节点
function getChildCategories($nodeId) {
$query = "SELECT node.* FROM categories AS node,
categories AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND parent.id = " . (int)$nodeId;
$result = mysqli_query($connection, $query);
return mysqli_fetch_all($result, MYSQLI_ASSOC);
}
闭包表模型(Closure Table Model)
闭包表使用单独的关系表来存储节点之间的所有路径关系,是最灵活的实现方式。
// 数据库表结构示例
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 getChildCategories($nodeId) {
$query = "SELECT c.* FROM categories c
JOIN category_paths cp ON c.id = cp.descendant
WHERE cp.ancestor = " . (int)$nodeId;
$result = mysqli_query($connection, $query);
return mysqli_fetch_all($result, MYSQLI_ASSOC);
}
实现建议
邻接表模型简单易实现,适合层级不深且不频繁查询的场景。嵌套集和闭包表查询效率高,但维护成本较高。路径枚举实现简单且查询方便,但路径长度有限制。
在实际应用中,可以根据业务需求选择合适的方法。对于中小型项目,邻接表或路径枚举通常足够;对于大型复杂项目,建议考虑嵌套集或闭包表。






