[PHP/MYSQL]Menü in Baumstruktur erstellen...

BartTheDevil89

Devilution Media
ID: 87739
L
2 Mai 2006
3.960
103
Hallo,

ich möchte ein Menü mit Baumstruktur erstellen. Also ich meine sowas hier:

Auto
- Sub1
- Sub2
-- Untersub1
-- Untersub2
- Sub3
Meine
- Sub4
- Sub5
...

Also ein Menü mit Unterpunkten, die sich beliebig weit nach unte ziehen.
Ich hab jetzt folgende Datenbankstruktur erstellt:

id/name/top

id also die Id, name ist der Titel und top hat die id des darüberliegenden drin.

Jetzt muss ich ja das Menü irgendwie ausgeben. Allerdings hab ich dabei jetzt paar Probleme. Denn:
Ich weiß, dass ich es über eine Funktion machen muss. Also ich rufe die erste Ebene auf also die Einträge in dem top = 0 ist. Jetzt muss ich überprüfen, ob es Einträge mit top = $idDesEintragesInDerErstenEbene gibt. Wenn ja, soll er weiter nach unten vorgehen, wenn nein einfach die Funktion weiter durchlaufen.

Aber wie läuft das...wie schaffe ich es, dass er eben weiter nach unten dann geht? Ich hab jetzt schon meine Funktion mal soweit gemacht bis zu dem Schritt, wo das Problem auftritt:

PHP:
function makemenu() {

$result = mysql_query("SELECT * FROM menu_eintrag where top = 0");
while ($line = mysql_fetch_array($result)) {
$menureturn .= "$line[id]<br>";
$menuid = $line['id'];
$numresult = mysql_query("SELECT * FROM menu_eintrag where top = '$menuid'"); 
$rows = mysql_num_rows($numresult);
if($rows != 0){
//ab hier dann weiter in die Tiefe gehen
}
}
mysql_free_result($result);
return $menureturn;
}


Kann mir jemand helfen?

Danke:roll:
 
Nunja, Du müsstest an der Stelle dann den Baum weiter nach unten verfolgen. Voraussichtlich mit einer rekursiven Funktion, die Dir das Menü erstellt.

Aber ganz ehrlich würde ich Dir von der Methode abweisen. Du hast dann X DB-Queries, obwohl Du das Ganze mit einem einzigen und entsprechender Logik auf PHP-Seite vermutlich effizienter abbilden kannst.

Ich würde erstmal alle Einträge aus der Datenbank auslesen (am besten geordnet nach "top=0", damit die Wurzelknoten am Anfang stehen), dann das Resultset durchlaufen und dabei das Menü aufbauen. Braucht keinerlei Rekursion, nur ein bisschen Gehirnschmalz, um die Knoten an die richtige Stelle zu bringen.
 
Nunja, Du müsstest an der Stelle dann den Baum weiter nach unten verfolgen. Voraussichtlich mit einer rekursiven Funktion, die Dir das Menü erstellt.

Aber ganz ehrlich würde ich Dir von der Methode abweisen. Du hast dann X DB-Queries, obwohl Du das Ganze mit einem einzigen und entsprechender Logik auf PHP-Seite vermutlich effizienter abbilden kannst.

Ich würde erstmal alle Einträge aus der Datenbank auslesen (am besten geordnet nach "top=0", damit die Wurzelknoten am Anfang stehen), dann das Resultset durchlaufen und dabei das Menü aufbauen. Braucht keinerlei Rekursion, nur ein bisschen Gehirnschmalz, um die Knoten an die richtige Stelle zu bringen.


Naja, hast du vielleicht mal ein Beispiel irgendwo wie du das meinst? Denn würde es schon gern so machen, dass auch beliebig viele Untereinträge möglich sein sollen. Also auch beliebig Unterebenen.
 
Ich find grade nicht mehr, wo ich das mal in dieser Art ohne Rekursion gebaut habe. Aber ich setz mich nachher zu Hause mal hin und guck, ob ich's finde oder Dir zumindest anderweitig ein Beispiel geben kann.
 
Hallo

Willst du das ganze Menü immer komplett abgebildet haben? Also quasi alle Zweige geöffnet? Oder soll immer nur ein Teil des Menüs ganz zu sehen sein?

Rekursion ist eigentlich ziemlich einfach. Du machst eine Funktion, die sich selber immer wieder aufruft. (Hört sich komisch an, ist aber so.) Man muss nur aufpassen, dass irgendwann Schluss ist ;)

Wenn du wirklich alles zeigen willst, dann könnte man es so machen (ungetestet und aus dem Kopf aufgeschrieben):
PHP:
function getItems($p)
{
  $abfrage = "select * from x where top=$p";
  $erg = mysql_query($abfrage);
  while ($zeile=mysql_fetch_row($erg))
  {
    // Jetzt den Eintrag anzeigen
    ...

    // Und jetzt kommt die Rekursion
    // Die Funktion ruft sich selber wieder auf
    getItems($zeile[0]);
  }
}

getItems(0);  // Startet die ganze Sache
Das sollte funktionieren. Wenn du aber wirklich alles anzeigen willst, dann kann das recht uneffektiv werden, weil es sehr viele Abfragen werden können.

Ob es Sinn macht, sich alles zurück geben zu lassen und das von Hand durchzulaufen? Wenn es sehr viele Menüeinträge aber nur relativ wenige Ebenen gibt, dann wohl eher nicht. Ansonsten könnte das schon Sinn machen. Hier die Ausgabe zu bewerkstelligen wird aber recht kompliziert. Es muss ja nachher alles an der richtigen Stelle stehen.

Wenn du nur einen Zweig offen haben willst, dann gehst du von innnen nach außen. Das kann man auch mit Rekursion machen. Man fängt nur nicht ganz außen an, sondern mit dem innersten Element, welches man kennt und arbeitet sich bis top=0 hoch. Hoffe das ist verständlich.
 
Also eine Baumstruktur in einer Datenbank abzulegen und effizient auszulesen ist kein triviales Unterfangen, optimal sind dafür jedoch Nested Sets welche in einem Rutsch so einen Abhängigkeitsbaum lesen können, das schreiben gestaltet sich dafür etwas komplexer
 
Ich find grade nicht mehr, wo ich das mal in dieser Art ohne Rekursion gebaut habe. Aber ich setz mich nachher zu Hause mal hin und guck, ob ich's finde oder Dir zumindest anderweitig ein Beispiel geben kann.
DAnke, wäre nett.
Hallo

Willst du das ganze Menü immer komplett abgebildet haben? Also quasi alle Zweige geöffnet? Oder soll immer nur ein Teil des Menüs ganz zu sehen sein?

Beides...also ich möchte erstmal ne Übersicht über alle haben für Bearbeiten und so. Danach wollte ich dann dazu übergeben mir was zu überlegen, wie ich das umbaue, dass er nur den gewählten Zweig anzeigt, wenn ich zum Beispiel auf Untersub1 klicke, dass dann eben Auto und Sub2 offen ist. Gibts denn ne einfache Variante, die beides erlaubt?

Also eine Baumstruktur in einer Datenbank abzulegen und effizient auszulesen ist kein triviales Unterfangen, optimal sind dafür jedoch Nested Sets welche in einem Rutsch so einen Abhängigkeitsbaum lesen können, das schreiben gestaltet sich dafür etwas komplexer

Genau deswegen steh ich ja vor dem Problem^^...werd mir den wiki-link allerdings mal durchlesen. DAnke
 
Nope, sorry. Ich hab zwar gefunden, was ich meinte, aber dort arbeite ich mit doppelt verknüpften Listen, was das Arbeiten ohne Rekursion um ein Vielfaches einfacher macht und leider verhindert, dass ich die Lösung auf Dein Problem anwenden könnte.

Aber so schlimm ist die Rekursion bei Deinem Problem gar nicht. Generell würde ich es so machen:

  • Du liest alle Einträge aus der Datenbank.
  • Anschliessend iterierst Du über alle Einträge und suchst diejenigen aus, die keinen Elterneintrag haben.
  • Nun iterierst Du über das entstehende Elternarray und suchst die jeweiligen Kinder raus.
  • Abschliessend iterierst Du über jeden Kinderast und suchst wiederum die Kinder raus.
 
Man könnte auch das ganze einfach über eine Rekursive Funktion lösen und den generierten HTML Code in einer Datei speichern. Der Html-Code könnte dann jeweils neu generiert werden, wenn etwas am Menü geändert wird (in der regel ist das ja relativ selten). Somit würden die vielen Datenbankabfragen doch sehr relativiert, da das menü nicht bei jedem aufruf neu aus der Datenbank gelesen wird.