dedlfix: Array mit Nested Set Werten zu Html-Liste/Menu verarbeiten

Beitrag lesen

Tach!

Spielen wir mal die Stack-Variante ausgehend von dem Array deines Eingangspostings durch. i = Element 0, das hat L=0 und R=3, es ist ein Elter. Das kommt auf den Stack, aber erstmal schauen, ob das L vom i+1 kleiner als unser R ist. Das ist der Fall, also gibt es mindestens einen Nachkommen, der Abstieg lohnt sich.

Ok soweit komme ich fast noch mit. Das bedeutet also, dass die Anzahl der Elemente auf dem Stack = der aktuellen Ebene sind? Also kann ich in jedem Schleifendurchlauf dem aktuellen Array den Wert hinzufügen?

In der Lösung brauchst du die Level-Angabe nicht mehr. Anhand des bereits in der Datenbank ermittelten Levels hätten wir sonst ab- und aufsteigen können. Aufgrund der Lücken haben wir aber von der Level-Lösung Abstand genommen. Aber ja, der Füllstand des Stacks repräsentiert auch das Level.

(Wenn das L allerdings kleiner als oder gleich unserem L ist, dann hast du einen Nebenbaum - allerdings passt diese Aussage nicht mehr, wenn es Teilbäume ohne Wurzeln gibt - aber vielleicht bekommst du sowas anhand der Menü-ID oder ähnlichem auseinandergehalten.)
Was meinst du damit? Es gibt keine Menüs innerhalb von Menüs. Also Menüpunkt X von Menü A wird niemals Menü B sein. Oder habe ich dich falsch verstanden?

Ich sah, dass du in der Tabelle mehrere Bäume abgelegt hast (je Menü einen). Wenn deine Abfrage immer nur Elemente eines Baumes/Menüs liefert, kannst du den Klammernsatz unberücksichtigt lassen. (Dürfte der Fall sein, weil du auf menu_id einschränkst.)

Ich habe es jetzt erstmal so. Es ist sicher nicht sehr elegant (das werde ich später optimieren) aber es scheint erstmal so zu funktionieren wie ich mir das vorgestellt habe.

Ja, nein. Wenn ein Elternelement ohne Kinder daherkommt, trifft keine deiner Bedingungen zu. (Zum Testen könntest du vor der das for schließenden Klammer noch eine Ausgabe (oder die()) setzen, wenn das ausgeführt wird, hast du einen Fall noch nicht berücksichtigt.) Ich würde die erste Bedingung so umschreiben, dass sie zunächst nur prüft, ob ein Elternelement vorliegt (L+1<R). Auch dann musst du ja eine Ausgabe vornehmen. Aber nun muss anhand von Kindern entschieden werden, ob abgestiegen werden soll, oder ob man sich das sparen kann. Das heißt, innerhalb des if(Elter)-Blocks kommt nun die Abfrage, ob das nächste Element ein Kind ist.

for($i = 0; $i < count($this->arrMenuItems); $i++){
    echo 'Name: '.$this->arrMenuItems[$i]['name']." - Level: ";

Du hast eine Menge Zugriffe auf das aktuelle Element. Es empfiehlt sich, $this->arrMenuItems[$i] in einer lokalen Variable ($current) abzulegen und die zu verwenden.

// letzten Elter suchen
    $arrParent = array_pop($this->arrStack);

Damit nimmst du den Elter auch vom Stack, was aber nur beim Aufsteigen passieren soll. Nimm an dieser Stelle end() und spar dir das Wiederdrauflegen. Beachte auch, dass array_pop() null und end() false liefert, wenn das Array leer ist.

$arrParent ist am Anfang ein leeres Array. Das müsste ich auch noch ändern.

Ah, das hast du schon bemerkt.

Den Stack am Ende zu leeren würde doch auch ein $arrStack = array() oder null am Ende reichen, oder warum überhaupt den Stack leeren? Kommt das zum tragen wenn ich direkt eine Html-Liste ausgebe?

Es geht nicht darum, die Variable aufzuräumen, sondern dass wenn da nochwas drinliegt, du noch abgestiegen bist. Für jedes Element, das da noch liegt, muss noch eine ul/li-Liste geschlossen werden.

$arrNested = array(  
  0 => array(  
    'leftkey' => 0,  
    'rightkey' => 5,  
    'name' => 'foo',  
  ),  
  1 => array(  
    'leftkey' => 1,  
    'rightkey' => 4,  
    'name' => 'bar',  
  ),  
);

Dieses Array enthält beide Fälle. Element 0 ist ein Elter mit Kind. Dem Element 1 fehlt das Kind (L2,R3). Es muss daher nicht auf den Stack. Nun ist das Array zu Ende und der Stack hat immer noch Element 0 draufliegen, und das muss noch abgebaut werden. Das Abbauen bekommst du quasi automatisch hin, wenn du wie nachfolgend ein Pseudo-Element ans Ende stellst. Das liegt wegen seiner L/R-Werte praktisch immer als Geschwist neben dem Root-Element, und um dahinzugelangen muss immer der Stack abgeräumt werden. Bei diesem Element musst du aber aufpassen, dass du davon nichts ausgibst, nur die Stack-Abbau-Nebenwirkung mitnimmst. Ansonsten müsstest du nach dem for nochmal den Stack-Abbau-Code explizit ausführen.

$arrNested = array(  
  0 => array(  
    'leftkey' => 0,  
    'rightkey' => 5,  
    'name' => 'foo',  
  ),  
  1 => array(  
    'leftkey' => 1,  
    'rightkey' => 4,  
    'name' => 'bar',  
  ),  
  2 => array(  
    'leftkey' => PHP_INT_MAX,  
    'rightkey' => PHP_INT_MAX,  
    'name' => 'nicht ausgeben',  
  ),  
);

dedlfix.