PHP bir ağaç yapısı halinde bu MPTT dizi dönüştürmek nasıl?

2 Cevap php

I Modified Preorder Tree Traversal formatında saklanan veritabanında hiyerarşik verileri var. "Tablo ORDER BY Left SELECT ID, Left, Right, Adı, vb;" Ben şöyle bir sorgudaki verileri çekiyorum. Ben bir ağaç yapısı içine DB bana verir düz bir dizi bu verileri dönüştürmek için çalışıyorum ki ben sonra olacak PHP'nin json_encode fonksiyonu ile JSON olarak çıktı.

Ben sorun benim ağaç yapısı kod olsa, ilk düzeyin ötesinde işe giderken yaşıyorum. Burada minimum test durum:

<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>

Ve burada ben çıkışı için alıyorum ne:

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) {
      }
    }
  }
}

Gördüğünüz gibi, bir yerde "Torunu" projectListToTree işlevinde çıktı orada olması gerektiğini belirtmek gibi görünüyor olsa da, kayıp oluyor. Bu ikinci seviye altında bir şey düşerse de ben atmak herhangi bir ağaç yapısı gibi görünüyor. Ne oluyor olabilir içine herhangi bir fikir?

Teşekkürler!

2 Cevap

Sorun bir dizi atama başvuruları kopya olmamasıdır, ama dizinin bir kopyasını yapar. Bu "Veli" düğümünün "çocuk" var "İkinci çocuk" dizi size "torun" eklemek aynı dizi, ama onun bir kopyası olmadığı anlamına gelir.

Sorunu gidermek için, açıkça yerine kopyalama referans atama kullanmak zorunda:

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];
}

Ampersan üç yerde eklendiğini unutmayın.

Bu sorun nedeniyle, bir php iç içe diziler ve atama operatörlerini kullanırken son derece dikkatli olmak zorundadır.

Bu da, iç içe geçmiş diziler içinde çok sayıda veri kullanarak işlemci ve bellek kullanımı ayak izi yoğun olduğu anlamına gelir. Örneğin, yukarıdaki örnekte, zaman projectListToTree () döner, (php çöp toplayıcı berbat beri) tam dizi ağaç yerel değişken $ ağacına kopyalanır ve iki kez bellekte olduğunu.

You) (array_pop aradığınız zaman görmek için bir echo deyimi koymak mı? Test olmadan bu okuma, ben yığın kapalı kaydını haşhaş ve atmadan düşünüyorum.