php实现树形结构
PHP实现树形结构的方法
树形结构在Web开发中常用于菜单、分类目录等场景。以下是几种常见的PHP实现方法。
递归方法实现树形结构
递归是最常见的树形结构实现方式,适合处理层级不确定的数据。
function buildTree(array $elements, $parentId = 0) {
$branch = array();
foreach ($elements as $element) {
if ($element['parent_id'] == $parentId) {
$children = buildTree($elements, $element['id']);
if ($children) {
$element['children'] = $children;
}
$branch[] = $element;
}
}
return $branch;
}
// 使用示例
$flatArray = [
['id' => 1, 'parent_id' => 0, 'name' => '节点1'],
['id' => 2, 'parent_id' => 1, 'name' => '节点1.1'],
['id' => 3, 'parent_id' => 1, 'name' => '节点1.2'],
['id' => 4, 'parent_id' => 0, 'name' => '节点2'],
];
$tree = buildTree($flatArray);
引用方法实现树形结构
对于大型数据集,引用方法比递归更高效。
function buildTreeWithReference(array $elements) {
$map = array();
$tree = array();
// 创建ID映射
foreach ($elements as &$element) {
$map[$element['id']] = &$element;
$element['children'] = array();
}
// 构建树
foreach ($elements as &$element) {
if ($element['parent_id'] != 0 && isset($map[$element['parent_id']])) {
$map[$element['parent_id']]['children'][] = &$element;
} else {
$tree[] = &$element;
}
}
return $tree;
}
使用嵌套集合模型
嵌套集合模型(Nested Set Model)是处理树形结构的高效方法,适合频繁查询但较少更新的场景。
数据库表结构示例:

CREATE TABLE categories (
id INT PRIMARY KEY,
name VARCHAR(255),
lft INT NOT NULL,
rgt INT NOT NULL
);
PHP实现查询子树:
function getSubtree($categoryId, $pdo) {
$stmt = $pdo->prepare("
SELECT node.id, node.name
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([$categoryId]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
使用预排序遍历树算法(MPTT)
MPTT(Modified Preorder Tree Traversal)是嵌套集合模型的实现方式,提供了高效的查询性能。
插入节点的PHP实现:

function insertNode($parentId, $nodeName, $pdo) {
// 获取父节点右值
$parent = $pdo->query("SELECT rgt FROM categories WHERE id = $parentId")->fetch();
// 更新其他节点的左右值
$pdo->exec("UPDATE categories SET rgt = rgt + 2 WHERE rgt >= {$parent['rgt']}");
$pdo->exec("UPDATE categories SET lft = lft + 2 WHERE lft >= {$parent['rgt']}");
// 插入新节点
$pdo->exec("INSERT INTO categories (name, lft, rgt) VALUES ('$nodeName', {$parent['rgt']}, {$parent['rgt']} + 1)");
}
使用第三方库
对于复杂项目,可以考虑使用专门的树形结构处理库:
-
baum/baum: Laravel的嵌套集合实现
// 安装 composer require baum/baum // 使用 $node = Category::create(['name' => '根节点']); $child = $node->children()->create(['name' => '子节点']); -
nicmart/tree: 通用的PHP树结构库
use Nicmart\Tree\Tree; use Nicmart\Tree\Node; $tree = new Tree; $root = new Node('根节点'); $tree->setRoot($root); $root->addChild(new Node('子节点'));
性能考虑
- 递归方法适合小型数据集和层级较少的情况
- 引用方法适合中型数据集,性能优于递归
- 嵌套集合模型适合大型数据集和频繁查询场景
- 第三方库通常提供了更完善的功能和更好的性能
选择哪种方法取决于具体应用场景、数据规模和性能要求。对于大多数Web应用,引用方法或嵌套集合模型是不错的选择。






