kerstel: Dynamisches Menü

Hi,

ich möchte für jeden User eine eigenes Menü, welches aus einer Datenbank generiert werden soll. Dieses Menü soll eine Baumstruktur haben, nun habe ich mir überlegt das jeder menü eintrag eine id hat, und jeder untereintrag zu einem eintrag hat genau die gleiche id, also so ungefär:

user | id | parent_id | Name
1    | 1  | 0         | Menü1
1    | 2  | 0         | Menü2
1    | 1  | 1         | Untermenü1 zu Menü1
1    | 2  | 1         | Untermenü2 zu Menü1
1    | 1  | 2         | Untermenü1 zu Untermenü2
usw.
in der ausgabe soll es dann so aussehen:
Menü1
+-Untermenü1
 -Untermenü2
 +-Untermenü1 zu Untermenü2
Menü2
usw.

Jetzt hab ich keine Ahnung wie ich das mit PHP machen soll, weil ich es zudem noch in eine Funktion packen wollte. Ich find irgendwie keinen Anhaltspunkt.

Hat da jemand n Lösungsvorschlag, oder n gibts für sowas n Tutorial, da ja jedes Forum sowas auch macht.

Gruß und Danke

Kerstel

  1. Hallo,

    ich möchte für jeden User eine eigenes Menü, welches aus einer Datenbank generiert werden soll. Dieses Menü soll eine Baumstruktur haben, nun habe ich mir überlegt das jeder menü eintrag eine id hat, und jeder untereintrag zu einem eintrag hat genau die gleiche id, also so ungefär:

    user | id | parent_id | Name
    1    | 1  | 0         | Menü1
    1    | 2  | 0         | Menü2
    1    | 1  | 1         | Untermenü1 zu Menü1
    1    | 2  | 1         | Untermenü2 zu Menü1
    1    | 1  | 2         | Untermenü1 zu Untermenü2

    Der Ansatz ist schon mal fast perfekt. :-)
    Jedoch sollte die ID eindeutig sein und nicht per Level definiert sein. (was machst Du mit 2fachen Untermenüs?) Also so:

    user | id | parent_id | Name
    1    | 1  | 0         | Menü1
    1    | 2  | 0         | Menü2
    1    | 3  | 1         | Untermenü1 zu Menü1
    1    | 4  | 1         | Untermenü2 zu Menü1
    1    | 5  | 2         | Untermenü1 zu Untermenü2

    Jetzt hab ich keine Ahnung wie ich das mit PHP machen soll, weil ich es zudem noch in eine Funktion packen wollte. Ich find irgendwie keinen Anhaltspunkt.

    Stichwort rekursive Funktionen. Sagt Dir das was? Lasse einfach eine Funktion rekursiv über alle Einträge drüberlaufen und ordne jedem Eintrag die eine Zahl zu, wie weit dieser Eingerückt ist.

    Das Ergebnis sollte dann so aussehen:

    Name                      | ID | Einrückung
    Menü1                     | 1  | 0
    Untermenü1 zu Menü1       | 3  | 1
    Untermenü2 zu Menü1       | 4  | 1
    Menü2                     | 2  | 0
    Untermenü1 zu Menü2       | 5  | 1

    Dann kannst Du daraus die Ausgabe zusammenbasteln (wie immer Du auch willst)

    Grüße,

    Christian

    P.S.:

    noch eine kleine Anregung: wie wäre es, wenn Du die Menü's generell vergibst und den Benutzern dann über eine Tabelle verschiedene Rechte gibst?

    Also z.B.

    Tabelle 1: Menü

    id | parent_id | Name
    1  | 0         | Menü1
    2  | 0         | Menü2
    3  | 1         | Untermenü1 zu Menü1
    4  | 1         | Untermenü2 zu Menü1
    5  | 2         | Untermenü1 zu Untermenü2

    Tabelle 2: Benutzer

    id | Name
    1  | Administrator
    2  | Sonstwas

    Tabelle 3: Zuordnung (jeder Eintrag bedeutet: Recht ist da)

    benutzer_id | menue_id
    1           | 1
    1           | 2
    1           | 3
    1           | 4
    1           | 5
    2           | 1
    2           | 3
    2           | 4

    So darf dann der Benutzer Administrator auf die Punkte 1-5 zugreifen und der Benutzer Sonstwas nur auf die Punkte 3-4.

    1. Hi,

      Der Ansatz ist schon mal fast perfekt. :-)
      Jedoch sollte die ID eindeutig sein und nicht per Level definiert sein. (was machst Du mit 2fachen Untermenüs?) Also so:

      user | id | parent_id | Name
      1    | 1  | 0         | Menü1
      1    | 2  | 0         | Menü2
      1    | 3  | 1         | Untermenü1 zu Menü1
      1    | 4  | 1         | Untermenü2 zu Menü1
      1    | 5  | 2         | Untermenü1 zu Untermenü2

      Stimmt, klingt logisch. Nur beim letzten Eintrag muss die parent_id = 4 sein, oder?

      Stichwort rekursive Funktionen. Sagt Dir das was?

      Sagt mit jetzt nichts, gibts dazu doku?

      noch eine kleine Anregung: wie wäre es, wenn Du die Menü's generell vergibst und den Benutzern dann über eine Tabelle verschiedene Rechte gibst?

      Glaub nicht dass das geht, da dies ein CMS sein soll und das menü soll die navigation der seite wiederspiegeln

      Danke und Gruß

      Kerstel

      1. Hallo,

        Stimmt, klingt logisch. Nur beim letzten Eintrag muss die parent_id = 4 sein, oder?

        oops - ist mir gar nicht aufgefallen (dann ist auch das andere Diagramm falsch)

        Sagt mit jetzt nichts, gibts dazu doku?

        Rekursiv heißt, dass die Funktion sich selber aufruft (und dabei möglichst keine Endlosschleife produziert ;) )

        Doku im Internet wüßte ich jetzt nicht ... hab' mal kurz gegoogled und mal abgesehen von UNI-Material (was sehr theoretisch und abstrakt ist) habe ich ein extrem einfaches Beispiel gefunden - da isses sogar in JavaScript: http://www.robert-web.de/rekursiv.shtml Vielleicht gibt's Dir ja einen ersten Einblick.

        Noch etwas: bei Rekursiven Funktionen wird's erst richtig nett, wenn Du werde in zwei Richtungen (Verschachtelungsebenen rauf/runter) übertragen musst - da musst Du erst mal wirklich überlegen.

        Da Du aber 0 Ahnung hast, programmiere ich mal schnell das Grundgerüst:

        Eine Rekursive Funktion für so eine Liste müsste aber etwa so verfahren:

        Vorraussetzung: Es muss eine Funktion get_menu_list geben, die einen Array von assoziativen Arrays zurückliefern à la

        $list = array (
          array ("id" => 1, "name" => "...", "sonstwas" => "sonstwas"),
          array ("id" => 2, "name" => "...", "sonstwas" => "sonstwas"),
          array ("id" => 3, "name" => "...", "sonstwas" => "sonstwas")
        );

        function create_menu_tree ($user, $parentid = 0, $indent = 0)
        {
          $final_list = array ();
          $list = get_menu_list ($user, $parentid);
          // nun wird die liste abgearbeitet
          foreach ($list as $listitem) {
            $listitem["indent"] = $indent;
            $final_list[] = $listitem;
            $new_list = create_menu_tree ($user, $listitem["id"], $indent + 1);
            // wenn es Einträge für dieses Menü gibt
            if (count ($new_list) > 0) {
              $final_list = array_merge ($final_list, $new_list);
            }
          }
          return $final_list;
        }

        Die Funktion liefert dann eine Liste zurück, die Du dann z.B. so ausgeben kannst:

        $list = create_menu_tree ($user);

        foreach ($list as $listitem) {
          echo str_repeat ("  ", $listitem["indent"]);
          echo $listitem["name"];
          echo "<br />\n";
        }

        Dann käme so eine (Beispiel-)Ausgabe:

        Menü
          Untermenü
          Untermenü
            Unter-Untermenü
        Menü
          Untermenü

        Du könntest natürlich auch eine Tabelle ausgeben und vieles mehr - such Dir etwas aus ... :-)

        Glaub nicht dass das geht, da dies ein CMS sein soll und das menü soll die navigation der seite wiederspiegeln

        Naja - ich wußte ja nicht genau, wofür das gut sein sollte ...

        Grüße,

        Christian