# NestedSet - Algorithmus gesucht



## F.o.G. (2. Dezember 2003)

Hallo,

ich brauche einen Algorithmus für einen Nested Set Baum in MySQL.

Ich nutze einen NestedSet Baum mit mehreren Wurzeln, es befinden sich also mehrere Nested Sets in einer Tabelle. 

Ich möchte nun mit einer Abfrage alle Eltern eines Eintrags und deren Geschwister haben. Stellt man sich beispielsweise den Windows Explorer vor, so sieht man beim Navigieren in tieferen Ebenen ja nicht nur das aktuelle Verzeichnis und dessen 'Eltern', sondern auch die Unterverzeichnisse der Eltern.

Alle meine Versuche dahin schlugen bis jetzt fehl. 

-----

Ein zweiter Algorithmus den ich brauche ist, alle Geschwister eines Eintrags zu finden, ohne dabei auf die Eltern zurück greifen zu müssen ... Das muss doch auch irgendwie gehen. 
Ich speichere zwar das Level eines jeden Eintrag separat (ja man kann es auch errechnen), aber mit diesem Ansatz bekommt man unwillkürlich auch Einträge aus anderen Unterästen des selben Levels......

Ich hoffe hier ein paar Anregungen zu finden.

Ciao, Jörg


----------



## JohannesR (3. Dezember 2003)

Unter http://develnet.org/36.html findest du einen tollen Artikel über Nested Sets, evt. hilft dir das ja weiter. Ich bin allerdings auch schonmal dran gescheitert...


----------



## F.o.G. (3. Dezember 2003)

Vielen Dank, den Link kannte ich schon.

Dieses Tutorial war auch eines der ersten, die ich zum Thema gelesen habe, und es ist auch sehr gut.

Allerdings findet man nirgendwo weiterführende Queries (die vorletzte PHP Mag Ausgabe hatte einige gute). 

Das mit den Geschwistern habe ich nun anders gelöst. da ich mehrere Wurzelknoten in der DB habe muss ich bei der Geschwisterabfrage sowieso abfragen, ob es sich um einen Root Node handelt oder nicht. Da ich die Abfrage also sowieso machen muss, habe ich für alle Knoten die keine Wurzel sind ja auch die ElternID. 

Das erste Problem ist allerdings etwas komplexer, aber das muss gehen. Ich kann ja auch von einem beliebigen Punkt aus alle Unterkategorien ausgeben, also muss es ja auch umgekehrt gehen. ...... Naja..... Ich poste hier auch mal, wenn ich meine Klasse veröffentliche.

Ciao, Jörg


----------



## Act of Fate (4. Dezember 2003)

Ja, der Artikel war in der PHP-Mag

Wenn du diesen Artikel haben möchtest, wäre ich gerne bereit, dir den zur Verfügung zu stellen, sofern er nicht mehr online ist!


----------



## Nils Hitze (4. Dezember 2003)

Hab den Artikel auch gelesen aber mein PHPMAG beim Umzug 
verschlampt. Ist es vielleicht möglich mir die Seite ebenfalls zur
Verfügung zu stellen ?

Jona


----------



## Act of Fate (4. Dezember 2003)

Ja, klar doch, kann ich machen! Bloß wie, scannen oder kopieren und per Post, dass ist hier die Frage!

Was meint Ihr?


----------



## JohannesR (5. Dezember 2003)

Einscannen und hochladen?


----------



## F.o.G. (5. Dezember 2003)

Also ich persönlich brauch den Artikel nicht, da ich die PHP Mag abonniert habe. Trotzdem danke.

Ansonsten bastel ich gerade an meiner Klasse. es sind schon viele Abfragen machbar, wie zB. den Pfad von einer Wurzel bis zu einem bestimmten Zweig auszulesen oder alle Nachfahren zu bekommen. 
Ich bau jetzt noch Methoden zum verschieben der Äste.
Naja, mein Problem ist immer die Dokumentation, wahrscheinlich packe ich einfach eine per PHP Doc generierte Seite dazu .....

Naja....aber die Abfrage die ich hier gesucht habe, ist mir immer noch nicht eingefallen 

Ciao, Jörg


----------



## bn (6. Dezember 2003)

F.o.G. hat gesagt.:
			
		

> Hallo,
> 
> ich brauche einen Algorithmus für einen Nested Set Baum in MySQL.
> 
> ...


Vorrausgesetzt das du jedem Ast auch eine root_id zugewiesen hast (anders geht es eigentlich auch nicht), wäre es doch ein Lösungsansatz, zunächst die root_id des Astes zu bestimmen und anschließend über die root_id von der Wurzel an auszulesen.



> -----
> 
> Ein zweiter Algorithmus den ich brauche ist, alle Geschwister eines Eintrags zu finden, ohne dabei auf die Eltern zurück greifen zu müssen ... Das muss doch auch irgendwie gehen.
> Ich speichere zwar das Level eines jeden Eintrag separat (ja man kann es auch errechnen), aber mit diesem Ansatz bekommt man unwillkürlich auch Einträge aus anderen Unterästen des selben Levels......
> ...


Auch hier sollte die root_id helfen.

Ich benutze folgende Tabellenstruktur:

```
CREATE TABLE `kategorien` (
  `baum_id` int(10) unsigned NOT NULL auto_increment,
  `root_id` int(10) unsigned NOT NULL default '0',
  `lft` int(10) unsigned NOT NULL default '0',
  `rgt` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`baum_id`),
  KEY `root_id` (`root_id`)
)
```
Es wird zu jedem Ast die root_id gespeichert.
Der Vorteil an diesem Modell ist, das ich nicht das Level extra speichere sondern aus einem Querry errechne.
aufbauend auf:
http://ffm.junetz.de/members/reeg/DSP/node10.html

viele Grüße
bloddy newbie


----------



## F.o.G. (9. Dezember 2003)

Release der Nested Set Klasse aus dem C*B Projekt

Hi, Ich habe meine Klasse jetzt auf 
Content*Builder.de veröffentlicht, genauer gesagt hier

Da ich das selbe DB Modell verwende wie DB_NestedSet (also mit parentID, level und mehreren Wurzeln), sind viele der Methoden Namen die selben. 

Die Klasse bietet aber viele Abfrage Methoden, braucht auch kein PEAR (das war der Hauptgrund für die Erstellung, da PEAR leider immer noch nicht auf jedem Server korrekt eingerichtet ist).

Die Klasse lockt die MYSQL Tabelle direkt, es ist also keine zusätzliche Lock Tabelle wie bei DB_NestedSet erforderlich. 

Was die Klasse noch nicht kann ist das verschieben von Zweigen oder das Sortieren.

Viel Spaß und postet euer Feedback.

Ciao, Jörg


----------



## MiLa (9. Dezember 2003)

Traue mich kaum zu fragen  
Aber kann mir jemand erklären, was NetsedSets sind?

Habe soetwas noch nie gehört und kein ordentliche Erklärung via http://www.g00gl3.de gefunden.
(Vieleicht habe ich nicht lange genug gesucht...)  

Vieleicht kann das hier ja jemand mit einigen Worten erklären...


----------



## Razorhawk (9. Dezember 2003)

Ich höre davon direkt auch das erstmal, aber soweit ich mich mit SQL und Bäumen auskenne ist das eine Methode um aus SQL Bäume erstellen zu können ohne eine rekursive unktion zu nutzen, welches einen erheblichen Geschwindigkeitsvorteil hat!
Diese Bäume kann man dann beliebig nutzen und mit ihnen Arbeiten.
Ich denke mir, dass das sehr gut sein könnte wenn man einen Explorer machen will, der sich dann für alles mögliche nutzen lässt... einfachstes Beispiel wäre ein Stammbaum deiner familie der bis 2000 jahre zurück geht und über 5000 Verwandte fasst (nur ein beispiel)

ich hoffe ich habe mich nicht zu weit aus dem Fenster gehängt, denn NestedSet höre ich vom begriff das erste mal.


----------



## F.o.G. (9. Dezember 2003)

Johannes Röttger hatte weiter oben schon einen Link zu einem guten Tutorial gepostet: http://develnet.org/36.html

NestedSet sind Bäume in SQL. Sie sind performanter als das Pfad Modell und erst recht als das Parent Child Modell. 

Bei Nested Sets speicherst du zu jedem Knoten des Baumes 2 ID Werte: left und right.
Beim Wurzelknoten ist left per Definition = 1 und right = 2, wenn der Knoten keine Kinder enthält. Kommt nun ein Kind dazu, umschließen die left und right Werte der Eltern die der Kinder. 

Kommt also zu unserem Knoten ein Kind hinzu, hat es für left = 2 und für right = 3. Die Elternrubrik hat nun aber einen right Wert von 4, es soll ja das Kind umschließen.

Du siehst hier vielleicht schon den Hasenfuß an der Sache: Lösch mal einen Knoten. Dann kann es im ungünstigsten Fall dazu kommen, dass alle anderen Knoten angepasst werden müssen. Aber dafür gibt es ja Klassen wie CB_NestedSet oder PEAR:B_NestedSet 

Das gute an Nested Sets sind die Abfragemöglichkeiten. Ich bekomme mit EINEM Query alle Kinder eines bestimmten Zweiges. Bei Parent Child muss du für jeden Zweig ein einzelnes Query absetzen, um an dessen Kinder zu kommen. 

Genau das gleiche Problem haben wir beim Parent Child Modell bei der Abfrage der Eltern. Da muss ich rekursiv jedes Level durchlaufen, wenn ich den Pfad von der Wurzel bis zum aktuellen Knoten haben will. Bei Nested Sets reicht hier wieder ein einziges 

Überzeugt? Schaus dir mal an, das ist echt genial das System.

Ciao, Jörg


----------



## F.o.G. (9. Dezember 2003)

Razorhawk: 

Du kannst das auch für Foren nehmen um ein Threaded Forum zu kreieren (also nicht wie hier, ein Flat Forum). 

Bei Content*Builder werden natürlich jetzt die Rubriken per NestedSets angelegt aber ich habe auch eine Erweiterung zur Verwaltung von Immobilien. Dort sind die Regionen und die Objekttypen als NestedSets abgelegt. 
Da ist das geniale, dass ich nach einer Tabellenverknüpfung zwischen Regionen und Immobilien alle Objekte bekomme, die in einer bestimmten Region liegen. Aber ich muss nur wissen, welches die gewählte Region ist, alle Unterregionen werden dann per Definition mit geladen und ich bekomme auch alle Objekte die darin liegen ohne die Unterregionen explizit abzufragen.

Vielseitig wie man sieht 

Ciao, Jörg


----------



## Razorhawk (9. Dezember 2003)

Mal rein theoretisch gesehen.
Dann wäre der dämliche Windows-Explorer ab unf zu wesentlich schneller wenn er diese methode nutzen würde


----------



## JohannesR (10. Dezember 2003)

> _Original geschrieben von F.o.G. _
> *Razorhawk:
> 
> Du kannst das auch für Foren nehmen um ein Threaded Forum zu kreieren (also nicht wie hier, ein Flat Forum).
> ...



Da man Threaded-Foren auch Flat darstellen kann, kann man auch Flat-Foren mit NestedSets bastln! 
Übrigens nette Klasse, vielen Dank!


----------



## F.o.G. (11. Dezember 2003)

da hast du vollkommen recht. Das will ich nämlich demnächst in Angriff nehmen. Man soll dann im Adminitrationsbereich einstellen können, wie das Forum dargestellt werden soll. 

Im Userbereich nicht, weil das unter Umständen verwirrend wird, wenn der eine User threaded guckt und der andere flat 

Ich liebe Nested Sets. In Content*Builder bau ich die derzeit in die Artikelverwaltung ein, um zum Beispiel Kapitel wie in einem Buch damit realisieren zu können. Auch kann man so Dachartikel zu einem Thema verfassen und andere Authoren können ihre Artikel unter dieses Dach stellen. Das ist zumindest schneller als die Verlinkung über Keywords, wo man ja mit Suchmustern einen erheblichen Geschwindigkeitsverlust hat....

Die Klasse wird immer mit C*B ausgeliefert aber ich werde die Klasse von Zeit zu Zeit aktualisiert ins Download Archiv stellen.

Ciao, Jörg


----------



## JohannesR (11. Dezember 2003)

Kannst du mal ein Anwendungsbeispiel posten, zum dran-entlang hangeln?


----------



## F.o.G. (11. Dezember 2003)

Ach verdammt, ich habe gerade gemerkt, dass im Zip Verzeichnis irgendwas durcheinander gekommen ist. Die KlassenDoku sollte da eigentlich unter doc liegen..... 

Naja, egal. Ein Beispiel? Kein Problem:

Nehmen wir diese Tabelle an

```
CREATE TABLE menu (
  `name` varchar(255) NOT NULL default '',
  `nodeID` int(10) unsigned NOT NULL default '0',
  `parentID` int(10) unsigned NOT NULL default '0',
  `rootID` int(10) unsigned NOT NULL default '0',
  `leftID` int(10) unsigned NOT NULL default '0',
  `rightID` int(10) unsigned NOT NULL default '0',
  `level` int(10) unsigned NOT NULL default '0',
  `order_num` int(10) unsigned NOT NULL default '0',
  KEY `rootID` (`rootID`),
  KEY `leftID` (`leftID`),
  KEY `rightID` (`rightID`),
  KEY `level` (`level`),
  KEY order_num (`order_num`),
  PRIMARY KEY ( `nodeID` )
) TYPE=MyISAM;
```

In deiner PHP Datei musst du natürlich erst mal die Klasse einbinden und dann über die Methode factory ableiten (factory pattern deswegen, um das ganze später mal leichter an PEAR:B oder PEAR::MDB anpassen zu können). Die Methode erwartet mind. 1 Array mit den 7 wichtigen Daten table, id, parent, root, l, r, level und order_num. 

Mit diesen 7 Feldern ist es dann auch problemlos möglich, einfach mal PEAR:B_NestedSet einzusetzen (wenn es mal bugfreier ist).

Das 2. Array ist für die zusätzlichen Felder gedacht, in unserem Beispiel das Feld name. Man soll ja bei der Erschaffung eines Knotens auch solche Werte gleich mit übergeben können. Ich geh einfach mal davon aus, dass man immer mindestens ein Feld hier drin stehen haben wird, nämlich den Namen des Knotens.

In den Array's stehen die Feldnamen auf der rechten Seite, die Aliasnamen auf der linken. Die Aliasnamen im $params Array sind fest und müssen so lauten.

Beispiel:

```
<?php
/*
* Nested Set Klasse einfügen
*/
require_once("CB_NestedSet.class.php");

/* 
* Nested Set Objekt für Typen anlegen 
*/
$params = array (
	'table'   => 'menu',
	'id'      => 'nodeID',
	'parent'  => 'parentID',
	'root'    => 'rootID',
	'l'       => 'leftID',
	'r'       => 'rightID',
	'level'   => 'level',
	'norder'  => 'order_num'
);

$additional = array (
	'name'           => 'name'
);

$nestedSet = CB_NestedSet::factory($params, $additional);
?>
```

Man hat nun ein NestedSet Objekt. 

Beim einfügen eines neuen Knotens muss man unterscheiden, ob man einen Wurzelknoten oder einen Kindknoten erschaffen will. 

Man muss die zusätzlichen Felder die zu füllen sind per Array übergeben:

```
$additional = array (
    "name" => "Name des Knotens"
);
```

Für Wurzelknoten nimmt man:

```
$id = $nestedSet->createRootNode($additional);
```

Bei Kindknoten nimmt man:

```
$id = $nestedSet->createSubNode($parentID, $additional);
```

Natürlich ist auch löschen möglich:

```
$id = $nestedSet->deleteNode($nodeID);
```

So...nun aber zu den Schmankerln meiner Klasse: den Abfrage Methoden. 
Es werden ja jetzt schon einige Methoden geboten. Jede Methode die nur einen Knoten abfragt liefert ein Array mit den Feldwerten direkt zurück. Wenn es keinen Knoten gab, wird immer false zurück geliefert.

Beispiel: 

```
$node = $nestedSet->getNode($id);
$nodeID = $node[nodeID];
$nodeName = $node[name];
```

Wie man sieht, muss man die Felder so ansprechen, wie die Tabellennamen in der Datenbank lauten. Im Gegensatz dazu muss man beim Erzeugen der Knoten beim Additional Array immer das als Feldnamen angeben, was man beim Ableiten der Klasse auf der linken Seite angegeben hat.

Man kann dieses Verhalten aber ändern:

```
$node = $nestedSet->getNode($id, true);
$nodeID = $node[id];
$nodeName = $node[name];
```

Als 2. Parameter wurde hier die Verwendung von Aliasnamen bei den zurück gelieferten Einträgen als Feldnamen auf true gesetzt. Man kann erkennen, dass man nicht mehr nodeID angeben muss, um an die ID zu kommen, sondern den Alias id.

Wenn man eine Methode aufruft, die mehr als einen Knoten zurückliefern kann, bekommt man immer ein Array, dessen erstes Level die ID enthält und im 2. Level die Werte dieses Knotens. Die Knoten werden in der richtigen Reihenfolge geliefert.

Beispiel:


```
$pathNodes = $nestedSet->getPath($id, true);
if($pathNodes != false) {
    $multiple = false;
    foreach($pathNodes as $k => $v) {
        if($multiple) { 
            echo " >> ";  
        }
        echo $v[name];
        $multiple = true;
    }
}
```

In diesem Beispiel wird der Pfad von der Wurzel zu einem bestimmten Knoten abgefragt und ausgegeben

Noch ein Beispiel mit Einrückung:


```
$branchNodes = $nestedSet->getBranch($id, true);
if($branchNodes != false) {
    foreach($branchNodes as $k => $v) {
        for($z = 1; $z <= $v[level]; $z++) {
            echo "&nbsp;";
        }
        echo $v[name].", ID: ". $v[id] ."<br>";
    }
}
```

Will man beispielsweise in einem Forum nur alle Topics ausgeben, genügt folgendes:


```
$rootNodes = $nestedSet->getRootNodes($id, true);
if($rootNodes != false) {
    foreach($rootNodes as $k => $v) {
        echo $v[name].", ID: ". $v[id] ."<br>";
    }
}
```

Einrückung wird ja hier nicht benötigt, da Rootnodes ja immer level = 1 haben. Aber ich entdecke gerade ein kleines Problem: will man die Sortierung nach Datum vornehmen (oder Datum des letzten Eintrags), kann man das bisher noch nicht ..... In der nächsten Version liefere ich eine Option zur Modifikation des SQL Statements nach.....

Naja, und so kann man sich durch die Methoden arbeiten.
getDescendants() gibt alle Kinder eines Knotens aus, exklusive dem Knoten selber. 
getBranch() macht das ganze inklusive des Knotens. 
getSiblings() liefert alle Geschwister
getParent() gibt die direkte Mutter zurück, getParents() gibt alle Eltern zurück (naja, also Opa und Uropa ....  )

Und die Methode mit der man alle Voränger (also den Stammbaum) eines Knotens bekommt, die habe ich ja hier erfragt, aber noch immer nicht zusammenbekommen. Aber ich schaff das noch ....

So ...  kleine Erklärung dieser Klasse .... Wie gesagt, ist die erste Version. Die Versionsnummer resultiert aus der CVS ID, keine Ahnung warum die so hoch ist. Aber ich folge jetzt einfach der ID 

In einer der nächsten Versionen werde ich noch weitere Extras einbauen. Man kann dann einer get Methode ein BitFeld übergeben, dass einige Optionen markiert. Beispielsweise kann man dann angeben, ob man bei jedem Knoten zurück geliefert haben will, wie groß die Anzahl der Geschwister ist oder wieviele Nachkommen ein Knoten hat (wieder: Berechnung erfolgt direkt in der Datenbank durch den Query).

Ciao, Jörg


----------



## JohannesR (11. Dezember 2003)

Wow! Verflucht, herzlichen Dank! Sehr gut erklärt und ausführlich! Das könnte man eigentlich glatt in Tutorials verschieben/kopieren, denke ich! Eigentlich bewerte ich keine Themen, aber in diesem Fall: 5 Sterne!


----------



## F.o.G. (12. Dezember 2003)

Ich habe eine aktualisierte Version unter Content*Builder  online gestellt. 

Das ist eine reine Bugfix Version, da es einige Server gibt, die magic_quotes oder so aus haben (irgendwas mit dieser Einstellung muss es sein). Jedenfalls funtkionierte die Klasse auf solchen Servern net.

Ciao, Jörg


----------



## F.o.G. (8. Februar 2004)

Version 1.5 von CB_NestedSet ist nun auch verfügbar. Möglich ist nun auch das verschieben und sortieren von Zweigen.

Wer immer die aktuellste Version haben will, kann sich diese auch aus den Content*Builder Paketen aus dem lib Verzeichnis 'entwenden'.

Ciao, Jörg


----------



## F.o.G. (31. März 2004)

Version 1.6 ist nun verfügbar. 

Jede get Methode kann nun mit einem weiteren Parameter aufgerufen werden: $additionalSQL. Dieses Array kann vier Einträge haben (field, join, where, append), welche als zusätzliche SQL Statements in die Abfragen eingebaut werden.

Beispiel:

In Content*Builder werden in einer Sprachtabelle zusätzliche Sprachversionen für die Rubriken abgelegt. Diese Tabelle musste ich irgendwie mit der NestedSets Klasse verbinden. So kam dieses Feature zustande.
Wichtig ist hierbei, dass die Tabelle mit dem definierten NestedSet immer als Alias n bekommt. Daher müssen die Feldnamen der Nestedset Tabelle  mit n.feldName oder so angesprochen werden.


```
// Array mit zusätzlichen SQL Code
$additionalSQL = array (
	"field" => ", lang.text, lang.languageID",
	"join"  => "LEFT JOIN ".TABLE."_language AS lang ON lang.typeID = n.fid AND lang.type = 'column' AND lang.languageID = '$defaultLanguage'"
);
```

Das kann nun an eine beliebige Get Methode übergeben werden.


```
$nodeRequest = $nestedSet->getAllNodes(true, $additionalSQL);
```

Hoffe das nützt jemanden was, aber ich find das ganz brauchbar.

Ciao, Jörg Stöber


----------



## bilias (20. April 2004)

vorweg erstmal  topppp     ich habs auch schon versucht hinzubiegen und bin kläglich gescheitert 

aber eins fehlt mir   wo stelle ich in der klasse ne verbindung zur db her?

bei der Pear::NestedSets  übergebe ich beim initialisieren den $dns mit.  Wie weiß die Klasse in welcher DB sich die Tabelle befindet und wie die Zugangsdaten dorthin sind?


----------



## twam (21. April 2004)

Ich will meine bescheidene Navigation auch auf Nested Sets umstellen, da ich bis jetzt noch die Parent-Methode nutze. Ich habe nur sehr wenige Hits, da ist das zwar egal, aber unschön. 

Ich will mein Menü jedoch nie ganz ausgeklappt sehen. Eigentlich sollten immer nur die Hauptpunkte zu sehen und nur die Menüpunkte aufgeklappt sein, die man aufklappen muss um zur aktuellen Seite zu gelangen.

Wie mache ich das am intelligensten? Jemand ne gute Idee für ne Query und muss ich das am besten nachher mit PHP aussortieren?

Grüße
  Tobias


----------



## Sven Petruschke (21. April 2004)

Meine Meinung ist, dass man nicht bei jeder Art von Hierarchie auf Nested Sets zurückgreifen muss. Wenn Du Deine Navigation bereits umgesetzt hast, warum dann die Umstellung? Jedenfalls gibt es hier Verweise auf ausreichend Literatur zum Thema:

--> http://klempert.de/php/nested_sets/literatur/

snuu


----------



## twam (21. April 2004)

Die Literatur habe ich zum größten Teil durch. Mir ist nur noch keine intelligente Lösung eingefallen.

Warum Umstieg? Noch sind die beiden Webseiten wo es Verwendung finden soll recht klein, so das der Umstieg problemlos möglich ist. Auf Dauer will ich es aber umgestellt haben, damit ich nicht so viele Anfragen an die DB benötige.

Grüße
  Tobias


----------



## Sven Petruschke (21. April 2004)

Hier wird alles haarklein am Beispiel einer Threadstruktur eines Forums  erklärt:
--> http://www.develnet.org/36.html

Die Informationen solltest Du Problemlos auf die Navigationsstruktur umsetzen können.

snuu


----------



## twam (21. April 2004)

Ich glaube wir reden etwas aneinander vorbei.

Das Beispiel auf die Menüstruktur zur übernehmen ist kein Problem. Nur zeigt er bis jetzt immer den gesamten Baum an.







Wenn jetzt ein Besucher die Seiten "I" (rot) öffnet (die Grafik ist übrigens dem Tut entnommen), dann sollen alle Übergeordneten Elemente und gleichgestellte Elemente (aber keine die andere Eltern haben!) anzeigt werden (rosa). Diese Selektion stellt mein Problem dar.

Optional sollte man auch noch die Kinder von I (J und L) mit anzeigbar machen.


----------



## F.o.G. (22. April 2004)

twam: wenn du den Ast, der ausgewählt ist, komplett ausklappen willst, könntest du einerseits mit getRootNodes alle Wurzeleinträge abfragen und dann mit getBranch den gesamten Zweig der geöffnet ist. Danach kann man in einer foreach Schleife alle root Elemente durchgehen und bei dem geöffneten Zweig noch mal die Elemente dieser Abfrage.

Problematisch ist allerdings ein Menu, durch dass man sich Level für Level durchhangeln muss. Ich suche immer noch nach dem Algorithmus den ich im allerersten Post dieses Threads suche. Man kann zwar fabelhaft einfach alle Vorgänger abfragen, aber dessen Gechwister bekomme ich nicht. Somit tritt das Phänomen bei der Navigation auf, dass beim Wechsel von der 2. Ebene in die 3. Ebene alle Geschwister des Knotens in der 2. Ebene immer verschwinden, was einfach verwirrend ist. 

Die Klasse bekommt natürlich eine Methode dafür, sobald ich die Abfrage habe. Und es muss eine geben, denn man kann ja problemlos alle direkten Vorgänger abfragen.....

Ciao, Jörg


----------



## Ckling (23. April 2004)

*Menü mit Nested Sets*

Zuerst: Grosses Lob an Jörg  ! , ich habe seit langem versucht ein Menü mit Nested-Sets aufzubauen, bin aber oft daran gescheitert. Inzwischen habe ich eine "rudimentäre" Lösung, bei der ich mich von unten alle Parents emporhangle und je nach Bedarf (das ist für jeden Level einstellbar) die Siblings ausgebe oder nicht.
Das funktioniert auch Wunderbar. Für den Aufbau verwende ich das Feld [Norder] um die richtige Reihenfolge der [Nodes] zu haben.

Wenn ich allerdings Nodes umsortiere (MoveBranch etc.) dann wird das Feld [Norder] nicht mehr so befüllt, sie ich es erwarte (überall steht der Wert 6). Dadurch fällt meine Menü durcheinander, was erst durch manuelles Edieren des Feldes [Norder] wieder zu beheben ist. 

Gibt es bei MoveBranch eventuell einen Bug oder verstehe ich den Sinn des Feldes [Norder] falsch? Mein Verständnis ist, das [Norder] immer die Reihenfolge der Nodes innerhalb eines Branch wiederspiegelt.

Ciao und Danke

Christian


----------



## F.o.G. (23. April 2004)

norder ist nur für die Root Nodes wichtig. Das NestedSet Modell in seiner reinen Form geht von einem Wurzelknoten aus. Man kann dann anhand der leftID's ordnen. 

Wenn man aber mehrere Wurzeln haben möchte, muss man diese auf eine andere Art und Weise sortieren, denn jede Wurzel ist für sich genommen ein eigenes NestedSet.

Ciao, Jörg


----------



## F.o.G. (21. Mai 2004)

Hi. Demnächst werde ich ein kleines Update herausbringen.

Zum einen gibt es ein Problem mit getAllNodes(). Die Sortierung kann da momentan nicht anhand der Sortierung der Wurzelknoten vorgenommen werden (wie einige schon bemerkt haben). Ich habe aber schon eine Idee, wie ich das beheben kann.

Zum anderen sind wichtige Funktionen hinzugekommen: 
dem Attribut $additionalSQL das jeder get Methode übergeben werden kann, kann ein weiteres Array Entry übergeben werden, und zwar order.
man kann also jetzt auch andere Ordnungen vorgeben als die natürliche Ordnung, die in der DB liegt.
Aktuell programmiere ich nämlich ein Forum, dass sowohl threaded als auch Flat ausgegeben werden kann. Bei der flat Ansicht muss ich allerdings alle Replies anhand des Datums sortieren, wann die Antworten eingefügt wurden.

So ... also bis bald.

Ciao, Jörg


----------

