如何递归格式化PHP嵌套分类数组的完整树形结构?
将MySQL获取的嵌套分类数组转换为指定树形结构(PHP实现)
原始分类数组(从MySQL获取)
$data = [ [ 'categoryId' => '08adf337-a577-4038-86a6-a5cd16676dff', 'name' => 'ELECTRONICS', 'parentId' => 0, 'lft' => 1, 'rgt' => 20, 'level' => 0, ], [ 'categoryId' => '20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 'name' => 'TELEVISIONS', 'parentId' => '08adf337-a577-4038-86a6-a5cd16676dff', 'lft' => 2, 'rgt' => 9, 'level' => 1, ], [ 'categoryId' => '3fb68583-b9f3-4996-86fa-897c825767e4', 'name' => 'TUBE', 'parentId' => '20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 'lft' => 3, 'rgt' => 4, 'level' => 2, ], [ 'categoryId' => 'bca4d77f-9f6f-41da-ad66-e747edcb9482', 'name' => 'LCD', 'parentId' => '20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 'lft' => 5, 'rgt' => 6, 'level' => 2, ], [ 'categoryId' => '9726c8ff-7664-4494-bb2f-3b365e7a6743', 'name' => 'PLASMA', 'parentId' => '20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 'lft' => 7, 'rgt' => 8, 'level' => 2, ], [ 'categoryId' => '576a2266-9f11-4430-b81f-2ac2a536ad9a', 'name' => 'PORTABLE ELECTRONICS', 'parentId' => '08adf337-a577-4038-86a6-a5cd16676dff', 'lft' => 10, 'rgt' => 19, 'level' => 1, ], [ 'categoryId' => '062921a4-e9af-48f6-adba-d623ca2de4ae', 'name' => 'MP3 PLAYERS', 'parentId' => '576a2266-9f11-4430-b81f-2ac2a536ad9a', 'lft' => 11, 'rgt' => 14, 'level' => 2, ], [ 'categoryId' => '3a80ae89-5eba-4407-819c-944e1d360ed9', 'name' => 'FLASH', 'parentId' => '062921a4-e9af-48f6-adba-d623ca2de4ae', 'lft' => 12, 'rgt' => 13, 'level' => 3, ], [ 'categoryId' => '0a03f267-8646-4460-bce7-dc6993e337a3', 'name' => 'CD PLAYERS', 'parentId' => '576a2266-9f11-4430-b81f-2ac2a536ad9a', 'lft' => 15, 'rgt' => 16, 'level' => 2, ], [ 'categoryId' => 'fc9a25d0-a67a-4753-aed8-c148c9c95573', 'name' => '2 WAY RADIOS', 'parentId' => '576a2266-9f11-4430-b81f-2ac2a536ad9a', 'lft' => 17, 'rgt' => 18, 'level' => 2, ], ];
目标树形结构格式
$result = array(); $result['items'] = [ [ 'id' => '08adf337-a577-4038-86a6-a5cd16676dff', 'title' => 'ELECTRONICS', 'children' => [ [ 'id' => '20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 'title' => 'TELEVISIONS' ], [ 'id' => '3fb68583-b9f3-4996-86fa-897c825767e4', 'title' => 'TUBE' ], [ 'id' => 'bca4d77f-9f6f-41da-ad66-e747edcb9482', 'title' => 'LCD' ], [ 'id' => '9726c8ff-7664-4494-bb2f-3b365e7a6743', 'title' => 'PLASMA' ], [ 'id' => '576a2266-9f11-4430-b81f-2ac2a536ad9a', 'title' => 'PORTABLE ELECTRONICS', 'children' => [ [ 'id' => '062921a4-e9af-48f6-adba-d623ca2de4ae', 'title' => 'MP3 PLAYERS', 'children' => [ [ 'id' => '3a80ae89-5eba-4407-819c-944e1d360ed9', 'title' => 'FLASH' ] ] ], [ 'id' => '0a03f267-8646-4460-bce7-dc6993e337a3', 'title' => 'CD PLAYERS' ], [ 'id' => 'fc9a25d0-a67a-4753-aed8-c148c9c95573', 'title' => '2 WAY RADIOS' ] ], ], ], ] ];
PHP实现代码
方法1:递归构建(代码简洁,适合中小数据量)
function buildTree(array $data, $parentId = 0) { $tree = []; foreach ($data as $item) { if ($item['parentId'] == $parentId) { $node = [ 'id' => $item['categoryId'], 'title' => $item['name'] ]; // 递归查找当前节点的子节点 $children = buildTree($data, $item['categoryId']); if (!empty($children)) { $node['children'] = $children; } $tree[] = $node; } } return $tree; } // 生成目标结构 $result = [ 'items' => buildTree($data) ]; // 输出结果验证 print_r($result);
方法2:非递归构建(性能更优,适合大数据量)
function buildTreeNonRecursive(array $data) { // 按parentId分组所有节点,便于快速查找子节点 $nodeGroups = []; foreach ($data as $item) { $nodeGroups[$item['parentId']][] = [ 'id' => $item['categoryId'], 'title' => $item['name'], 'parentId' => $item['parentId'] ]; } // 从根节点开始构建树形结构 $tree = $nodeGroups[0] ?? []; foreach ($tree as &$node) { if (isset($nodeGroups[$node['id']])) { $node['children'] = $nodeGroups[$node['id']]; // 用栈处理深层子节点 $stack = $node['children']; while (!empty($stack)) { $child = array_pop($stack); if (isset($nodeGroups[$child['id']])) { $child['children'] = $nodeGroups[$child['id']]; array_push($stack, ...$child['children']); // 更新子节点数据 foreach ($node['children'] as &$c) { if ($c['id'] == $child['id']) { $c = $child; break; } } } unset($child['parentId']); } } unset($node['parentId']); } return $tree; } // 生成目标结构 $result = [ 'items' => buildTreeNonRecursive($data) ]; // 输出结果验证 print_r($result);
参考MySQL相关语句
分类表结构
CREATE TABLE categories ( categoryId VARCHAR(36) PRIMARY KEY, name VARCHAR(255) NOT NULL, parentId VARCHAR(36) DEFAULT '0', lft INT NOT NULL, rgt INT NOT NULL, level INT NOT NULL, INDEX idx_parentId (parentId), INDEX idx_lft_rgt (lft, rgt) );
数据插入SQL
INSERT INTO categories (categoryId, name, parentId, lft, rgt, level) VALUES ('08adf337-a577-4038-86a6-a5cd16676dff', 'ELECTRONICS', '0', 1, 20, 0), ('20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 'TELEVISIONS', '08adf337-a577-4038-86a6-a5cd16676dff', 2, 9, 1), ('3fb68583-b9f3-4996-86fa-897c825767e4', 'TUBE', '20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 3, 4, 2), ('bca4d77f-9f6f-41da-ad66-e747edcb9482', 'LCD', '20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 5, 6, 2), ('9726c8ff-7664-4494-bb2f-3b365e7a6743', 'PLASMA', '20150966-bbc5-438f-b3eb-1ff0bbc71b8b', 7, 8, 2), ('576a2266-9f11-4430-b81f-2ac2a536ad9a', 'PORTABLE ELECTRONICS', '08adf337-a577-4038-86a6-a5cd16676dff', 10, 19, 1), ('062921a4-e9af-48f6-adba-d623ca2de4ae', 'MP3 PLAYERS', '576a2266-9f11-4430-b81f-2ac2a536ad9a', 11, 14, 2), ('3a80ae89-5eba-4407-819c-944e1d360ed9', 'FLASH', '062921a4-e9af-48f6-adba-d623ca2de4ae', 12, 13, 3), ('0a03f267-8646-4460-bce7-dc6993e337a3', 'CD PLAYERS', '576a2266-9f11-4430-b81f-2ac2a536ad9a', 15, 16, 2), ('fc9a25d0-a67a-4753-aed8-c148c9c95573', '2 WAY RADIOS', '576a2266-9f11-4430-b81f-2ac2a536ad9a', 17, 18, 2);
树形数据查询SQL(嵌套集模型)
-- 查询完整树形结构,按lft排序保证层级顺序 SELECT * FROM categories ORDER BY lft ASC; -- 查询指定节点的所有子节点 SELECT c.* FROM categories c JOIN categories parent ON c.lft > parent.lft AND c.rgt < parent.rgt WHERE parent.categoryId = '08adf337-a577-4038-86a6-a5cd16676dff' ORDER BY c.lft ASC;
内容的提问来源于stack exchange,提问作者Ersin Güvenç
相关产品推荐
相关产品推荐

