CSS-Listennavigation mit PHP und MySQL erzeugen

WiZdooM

Erfahrenes Mitglied
Hallo

Ich bin grade dabei eine datenbankgestützte Navigation zu bauen.
Dafür habe ich vorgehabt, CSS-Listen mit Namen und Links aus der Datenbank zu füttern.

HTML:
<ul>
<li><a href="index.php?id=1">Home</a></li>
<li><a href="index.php?id=2">Aktuelles</a></li>
<li><a href="index.php?id=3">Unternehmen</a></li>
<ul>
<li><a href="index.php?id=4">Partner</a></li>
</ul>
<li><a href="index.php?id=5">Produkte</a></li>
<ul>
<li><a href="index.php?id=6">Fahrzeugprodukte</a></li>
<li><a href="index.php?id=7">Versicherungen</a></li>
</ul>
<li><a href="index.php?id=8">Messe-Galerie</a></li>
</ul>

Bisher habe ich eine Tabelle mit "id" und "topid". "id" ist der Primärschlüssel und "topid" der Verweis auf das übergeordnete Element.
In meinem Beispiel wäre jetzt z.B. "Partner" id=4;topid=3.

Mir ist es bis jetzt nur gelungen, die Rootelemente auszulesen und mit echo "<li><a href=". . ."></a></li>" zu erzeugen. Rootelemente und Childelemente liegen in jeweils einem Array vor.
Ich hab aber keine Ahnung, wie ich zwischendrin und an der richtigen Position die "<ul><li><a href=". . ."></a></li></ul>" integriere.

Hat jemand vielleicht einen Tip ?
 
Rootelemente und Childelemente liegen in jeweils einem Array vor.

Da wäre nun interessant zu Wissen welche Struktur es genau ist. Zum Beispiel so etwas (wie folgt)?
Code:
Eltern
  Kinder
    Spielzeug
Vater
  Sohn
    Mofa
    Motorrad
    Auto
Mutter
  Tochter
    Puppen
    Schminke
    Verkomplizierungsmaschine

Dann wäre es recht einfach. Oder meinst du eher so etwas?
Code:
[0] => Eltern, [1] => Kinder
[0] => Kinder, [1] => Spielzeug
[0] => Mutter, [1] => Tochter
...
 
Hallo

In meinem Fall habe ich bis jetzt nur zwei Ebenen: Die Root Ebene und eine Childebene, die kein, ein oder mehrere Elemente haben kann, aber nicht tiefer verzweigt. Unterseiten wie Partner haben also derzeit noch keine weiteren Unterseiten. Umgesetzt ist das wie aus dem Tutorial von dfd1.

PHP:
while ($nav_data = $mysql->fetcharray()) { 
    $nav_array[$i] = array('menu_ID'=>$nav_data["menu_ID"], 'menu_name'=>$nav_data["menu_name"]); 
    $i++; 
}

bzw.

PHP:
while ($subnav_data = $mysql->fetcharray()) { 
    $child_array[$i] = array('menu_ID'=>$subnav_data["menu_ID"], 'menu_name'=>$subnav_data["menu_name"], 'menu_topid'=>$subnav_data["menu_topid"], 'level'=>$invlevel); 
    $i++; 
}

Anmerkung am Rande:
Ich versuche die Webpräsens meiner Firma in ein MVC zu überführen. Derzeit könnte ich noch auf eine solche dynamische Navigation verzichten, aber ich weiß ja nicht was noch alles kommt.
 
PHP:
$child_array[$i] = array('menu_ID'=>$subnav_data["menu_ID"], 'menu_name'=>$subnav_data["menu_name"], 'menu_topid'=>$subnav_data["menu_topid"], 'level'=>$invlevel);

Das geht ein bisschen einfacher und dadurch sicherlich auch schneller, sofern es nur diese Einträge in $subnav_data gibt:
PHP:
$child_array[$i] = $subnav_data;
$child_array[$i]['level'] = $invlevel;

Noch etwas schnelleres: Wenn die Struktur des Menüs sich so gut wie nie ändert verwende NestedSets.

Für die Lösung deines Ansatzes, sollte es ein Array geben, das die gesamte Relation innerhalb der Tabelle repräsentiert (ID, Name, topID, level). Hier sieht man schon die Probleme der Performance, denn nun kommt eine rekursive Funktion hinzu (Pseudocode):
Code:
func genList(arr, rootID)
{
  ausgabe = "<ul>";

  for (i = 0; i < count(arr); i++)
  {
    if (array[i]["ID"] = rootID)
    {
      ausgabe += "<li>" + array[i]["name"] + genList(arr, array[i]["ID"]) + "</li>";
    }
  }

  // Wenn nichts generiert wurde, nichts zurück geben
  if (ausgabe == "<ul>")
  {
    return "";
  }

  ausgabe += "</ul>";
  return ausgabe;
}

Ich schätze die Laufzeit auf O(n²) - ohne Anspruch auf Richtigkeit. n² (mit n = "Anzahl Einträge") trifft es aber schon gut finde ich. Da lässt sich aber noch was mit der Tiefe drehen. Den Algo bastle ich gleich und poste ihn hier, wenn du nicht NestedSets nutzen wirst.
 
Zuletzt bearbeitet:
Hallo

Danke dir ganz Herzlich für den Denkanstoß. Ich komme jetzt allerdings vor dem Wochenende nicht mehr dazu das ganze umzusetzen, weil ich ein paar andere Dinge erledigen muss. Ich werde dir aber kommende Woche (so mein Boss will) Feedback geben, wie die Lösung final aussieht..
 
Zurück