我在数据库中有分层数据,存储在 Modified Preorder Tree Traversal 中格式。我在查询中提取数据,该查询类似于“SELECT ID, Left
, Right
, Name, etc FROM Table ORDER BY Left
;"。我正在尝试将此数据从 DB 给我的平面数组转换为树结构,然后我将使用 PHP 的 json_encode 函数将其输出为 JSON。
不过,我无法让我的树结构代码在第一层之外工作。这是一个最小的测试用例:
<pre><?php
function projectListToTree($projects) {
$stack = Array();
for($x =0; $x < count($projects); $x++) {
$project = $projects[$x];
$project['Children'] = Array();
while(count($stack) > 0 && $stack[count($stack) - 1]['Right'] < $project['Right']) {
array_pop($stack);
}
if(count($stack) > 0) {
$stack[count($stack) - 1]['Children'][] = $project;
echo "Adding " . $project['Name'] . " to " . $stack[count($stack) - 1]['Name'] . " for a total of "
. count($stack[count($stack) - 1]['Children']) . " kids\n";
} else {
echo "No parent\n";
}
echo "stack count: " . count($stack) . "\n";
array_push($stack, $project);
}
echo "Left in stack: " . count($stack) . "\n";
return $stack[0];
}
/*
This is basically what comes from the DB.
Should be:
Parent
First Child
Second Child
Grand Child
*/
$projects = Array(
Array(
"ID" => "2",
"Left" => "2",
"Right" => "9",
"ParentID" => "1",
"Name" => "Parent"
),
Array(
"ID" => "3",
"Left" => "3",
"Right" => "4",
"ParentID" => "2",
"Name" => "First Child"
),
Array(
"ID" => "4",
"Left" => "5",
"Right" => "8",
"ParentID" => "2",
"Name" => "Second Child"
),
Array(
"ID" => "5",
"Left" => "6",
"Right" => "7",
"ParentID" => "4",
"Name" => "Grand Child"
)
);
$tree = projectListToTree($projects);
echo "-----\n\n\n\n";
var_dump($tree);
?></pre>
这是我得到的输出:
No parent
stack count: 0
Adding First Child to Parent for a total of 1 kids
stack count: 1
Adding Second Child to Parent for a total of 2 kids
stack count: 1
Adding Grand Child to Second Child for a total of 1 kids
stack count: 2
Left in stack: 3
-----
array(6) {
["ID"]=>
string(1) "2"
["Left"]=>
string(1) "2"
["Right"]=>
string(1) "9"
["ParentID"]=>
string(1) "1"
["Name"]=>
string(6) "Parent"
["Children"]=>
array(2) {
[0]=>
array(6) {
["ID"]=>
string(1) "3"
["Left"]=>
string(1) "3"
["Right"]=>
string(1) "4"
["ParentID"]=>
string(1) "2"
["Name"]=>
string(11) "First Child"
["Children"]=>
array(0) {
}
}
[1]=>
array(6) {
["ID"]=>
string(1) "4"
["Left"]=>
string(1) "5"
["Right"]=>
string(1) "8"
["ParentID"]=>
string(1) "2"
["Name"]=>
string(12) "Second Child"
["Children"]=>
array(0) {
}
}
}
}
如您所见,“Grandchild”在某个地方迷路了,尽管 projectListToTree 函数中的输出似乎表明它应该在那里。似乎我扔给它的任何树结构都会掉落第二层以下的任何东西。对可能发生的事情有任何见解吗?
谢谢!
最佳答案
问题是分配一个数组并没有复制引用,而是复制了一个数组。这意味着,您在“父”节点的“ child ”中拥有的“第二个 child ”数组与您添加“孙子”的数组不同,而是它的副本。
要解决此问题,您必须明确使用引用分配而不是复制:
function projectListToTree($projects) {
$stack = Array();
for($x =0; $x < count($projects); $x++) {
$project = &$projects[$x];
$project['Children'] = array();
while(count($stack) > 0 && $stack[count($stack) - 1]['Right'] < $project['Right']) {
array_pop($stack);
}
if(count($stack) > 0) {
$stack[count($stack) - 1]['Children'][] = &$project;
echo "Adding " . $project['Name'] . " to " . $stack[count($stack) - 1]['Name'] . " for a total of "
. count($stack[count($stack) - 1]['Children']) . " kids\n";
echo "\n";
} else {
echo "No parent\n";
}
echo "stack count: " . count($stack) . "\n";
$stack[] = &$project;
}
echo "Left in stack: " . count($stack) . "\n";
return $stack[0];
}
请注意,在三个位置添加了一个符号。
由于这个问题,在 php 中使用嵌套数组和赋值运算符时必须格外小心。
这也意味着在嵌套数组中使用大量数据时,处理器使用率和内存占用量会很大。例如,在上面的例子中,当 projectListToTree() 返回时,完整的数组树被复制到局部变量 $tree 并且(因为 php 垃圾收集器很糟糕)在内存中两次。
关于php - 如何在PHP中将这个MPTT数组转换成树结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/823071/