php实现无限分类
实现无限分类的方法
无限分类通常用于构建树状结构数据,如商品分类、多级菜单等。以下是几种常见的实现方式:
递归实现法
递归是最直观的方法,通过函数自身调用来处理子分类:
function getTree($data, $pid = 0, $level = 0) {
static $tree = [];
foreach ($data as $k => $v) {
if ($v['pid'] == $pid) {
$v['level'] = $level;
$tree[] = $v;
getTree($data, $v['id'], $level + 1);
}
}
return $tree;
}
数据库表结构通常包含id、name、pid(父ID)字段。该方法适合数据量小的场景,但大数据量时递归性能较差。
闭包表实现法
闭包表(Closure Table)通过额外的关系表存储节点间所有路径:
CREATE TABLE category (
id INT PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE category_closure (
ancestor INT,
descendant INT,
depth INT,
PRIMARY KEY (ancestor, descendant)
);
查询所有子节点的SQL示例:
SELECT c.* FROM category c
JOIN category_closure cc ON c.id = cc.descendant
WHERE cc.ancestor = 1;
该方法查询效率高,但需要维护额外的关系表。
嵌套集模型
嵌套集模型(Nested Set Model)使用left和right值表示节点位置:
CREATE TABLE category (
id INT PRIMARY KEY,
name VARCHAR(50),
lft INT,
rgt INT
);
查询子树:
function getDescendants($categoryId) {
$category = getCategoryById($categoryId);
$sql = "SELECT * FROM category
WHERE lft BETWEEN {$category['lft']} AND {$category['rgt']}
ORDER BY lft";
return query($sql);
}
该方法查询效率高,但插入和移动节点时需要复杂的更新操作。
路径枚举法
通过path字段存储从根到当前节点的路径,如/1/2/5/:
CREATE TABLE category (
id INT PRIMARY KEY,
name VARCHAR(50),
path VARCHAR(255)
);
查询子节点:
function getChildren($categoryId) {
$sql = "SELECT * FROM category WHERE path LIKE '%/{$categoryId}/%'";
return query($sql);
}
该方法实现简单,但路径长度有限制,且移动节点需要更新所有子节点路径。
性能优化建议
对于大数据量场景,推荐使用闭包表或嵌套集模型。小数据量可使用递归或路径枚举法。实际选择需根据读写频率、数据量大小等权衡。







