php 无限分类的实现
无限分类的实现方法
递归方法
递归是处理无限分类的常见方法。通过递归函数可以遍历所有子分类。
function getTree($data, $pid = 0, $level = 0) {
static $tree = array();
foreach ($data as $key => $value) {
if ($value['pid'] == $pid) {
$value['level'] = $level;
$tree[] = $value;
getTree($data, $value['id'], $level + 1);
}
}
return $tree;
}
引用方法
使用引用方式构建树形结构,效率较高。
function makeTree($list) {
$tree = array();
$refer = array();
foreach ($list as $key => $data) {
$refer[$data['id']] = &$list[$key];
}
foreach ($list as $key => $data) {
$parentId = $data['pid'];
if ($parentId == 0) {
$tree[] = &$list[$key];
} else {
if (isset($refer[$parentId])) {
$parent = &$refer[$parentId];
$parent['children'][] = &$list[$key];
}
}
}
return $tree;
}
数据库设计
无限分类需要合理的数据库表结构设计。
CREATE TABLE `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`pid` int(11) NOT NULL DEFAULT '0',
`path` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
路径枚举法
使用path字段存储完整路径,如"1,2,5"表示其父级路径。
function getPath($id) {
$path = array();
while ($id > 0) {
$category = getCategoryById($id); // 假设有此函数
array_unshift($path, $category['id']);
$id = $category['pid'];
}
return implode(',', $path);
}
闭包表
使用额外的关系表存储节点间关系,适合复杂查询。
CREATE TABLE `category_closure` (
`ancestor` int(11) NOT NULL,
`descendant` int(11) NOT NULL,
`depth` int(11) NOT NULL,
PRIMARY KEY (`ancestor`,`descendant`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
前端展示
将分类树转换为HTML结构。
function renderTree($tree) {
$html = '<ul>';
foreach ($tree as $node) {
$html .= '<li>'.$node['name'];
if (!empty($node['children'])) {
$html .= renderTree($node['children']);
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
性能优化
对于大数据量分类,建议使用缓存。
function getCachedTree() {
$cacheKey = 'category_tree';
if (!$tree = Cache::get($cacheKey)) {
$list = Category::all()->toArray();
$tree = makeTree($list);
Cache::put($cacheKey, $tree, 1440);
}
return $tree;
}






