php实现无限分类
PHP实现无限分类的方法
无限分类是一种常见的数据库设计模式,适用于多层级分类结构(如商品分类、地区划分等)。以下是几种实现方式:
递归实现法
递归方法适合层级较少的情况,代码简洁但性能随层级加深可能下降。
function getTree($data, $pid = 0, $level = 0) {
static $tree = [];
foreach ($data as $v) {
if ($v['pid'] == $pid) {
$v['level'] = $level;
$tree[] = $v;
getTree($data, $v['id'], $level + 1);
}
}
return $tree;
}
数据库表结构示例:
CREATE TABLE `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`pid` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
);
闭包表设计法
通过额外的关系表存储所有节点间的路径,查询效率高但结构复杂。
-- 节点表
CREATE TABLE `node` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
);
-- 路径关系表
CREATE TABLE `path` (
`ancestor` int(11) NOT NULL,
`descendant` int(11) NOT NULL,
`depth` int(11) NOT NULL,
PRIMARY KEY (`ancestor`,`descendant`)
);
查询所有子节点:
$sql = "SELECT n.* FROM node n
JOIN path p ON n.id = p.descendant
WHERE p.ancestor = :parent_id";
预排序遍历树算法(MPTT)
通过左右值编码实现高效查询,适合读多写少的场景。
CREATE TABLE `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`lft` int(11) NOT NULL,
`rgt` int(11) NOT NULL,
PRIMARY KEY (`id`)
);
查询子树示例:
function getSubTree($rootId) {
$sql = "SELECT node.* FROM category AS node,
category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND parent.id = ?
ORDER BY node.lft";
// 执行查询...
}
扁平数组转树结构
从数据库获取扁平数组后,在PHP中转换为树形结构:
function buildTree(array $items, $parentId = 0) {
$branch = [];
foreach ($items as $item) {
if ($item['pid'] == $parentId) {
$children = buildTree($items, $item['id']);
if ($children) {
$item['children'] = $children;
}
$branch[] = $item;
}
}
return $branch;
}
性能优化建议
- 递归法适合层级固定且较浅的场景
- 闭包表在频繁查询时性能最优
- MPTT适合读多写少的业务场景
- 大数据量建议配合缓存使用
- 前端展示时可使用jQuery树插件如zTree或jsTree
每种方法各有优劣,选择时需根据具体业务场景的读写比例、数据量大小等因素综合考虑。







