簡體   English   中英

如何在PHP中將此MPTT數組轉換為樹結構?

[英]How to convert this MPTT array into a tree structure in PHP?

我在數據庫中有分層數據,以Modified Preorder Tree Traversal格式存儲。 我在一個看起來類似“SELECT ID, LeftRight ,Name等FROM FROM 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) {
      }
    }
  }
}

正如你所看到的,即使projectListToTree函數中的輸出似乎表明它應該存在,某個地方“孫子”也會迷路。 看起來我拋出的任何樹形結構都會降低第二級以下的任何結構。 對可能發生的事情的任何見解?

謝謝!

問題是分配數組不會復制引用,而是復制數組。 這意味着,您在“父”節點的“子”中擁有的“第二個子”數組與您添加“孫子”的數組不同,而是它的副本。

要解決此問題,您必須顯式使用引用分配而不是復制:

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垃圾收集器很糟糕)在內存中兩次。

你有一個echo語句,看看你何時調用array_pop()? 通過閱讀本文而不進行測試,我認為你正在從堆棧中彈出記錄並扔掉它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM