tutorials.de Buch-Aktion 05/2012
  • Menusystem mit PHP und MySQL

    Menusystem mit Untermenus

    Wir bauen heute ein Menusystem mit PHP und MySQL.

    Von der Ausgabe her soll es so aussehen:
    Code :
    1
    2
    
    Baum
    Blume
    und wenn wir auf Baum klicken, klappt darunter ein Untermenu auf:
    Code :
    1
    2
    3
    
    Baum
      Apfel
    Blume
    Das soll unbegrenzt weitergehen können. Eines schon vorweg: das ganze wird durch eine rekursive Funktion gemacht. (Eine Funktion ruft sich selbst auf)
    PHP-Code:
    <html>
    <
    head>
    <
    frameset cols="20%,80%">
        <
    frame src="baum.php3" name="navi">
        <
    frame src="haupt.php3" name="haupt">
    </
    frameset>


    </
    head>
    <
    body
    wir sehen das ganze geht über Frames. Links unser Menu, rechts unsere ausgewählte Seite.

    Machen wir uns mal erst Gedanken über den Aufbau der Datenbank die das Menu steuern soll:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    
    # Table structure for table `menu`
    CREATE TABLE menu (
      mid int(11) NOT NULL auto_increment,  = damit wir eine eindeutige Id haben über die alles gesteuert wird
      eintrag char(25) NOT NULL default '', = das wird angezeigt im menu (z.b unser Baum)
      vater int(11) NOT NULL default '0',   = hier steht die vater id drin
      href char(50) NOT NULL default '',    = die seite wird aufgerufen
      PRIMARY KEY  (mid)
    ) TYPE=MyISAM;

    Code :
    1
    2
    3
    4
    5
    6
    
    # Dumping data for table `menu`
    INSERT INTO menu VALUES (1, 'baum', 0, '');
    INSERT INTO menu VALUES (2, 'blume', 0, '');
    INSERT INTO menu VALUES (3, 'apfel', 1, 'apfel.htm');
    INSERT INTO menu VALUES (4, 'boskop', 3, 'boskop.htm');
    INSERT INTO menu VALUES (5, 'birne', 1, '');

    Zum Vater muss ich noch etwas loswerden: wenn der Vater 0 ist, dann ist der Eintrag im Hauptmenu. Ansonsten steht die id vom übergeordneten Menu oder auch "Vatermenu" darin. Unser Apfel hat ja als Vorgänger(vater)id die id vom Baum. Oder andersrum: Alles was als vater die id 1 hat, wird aufgeklappt, wenn der Baum angeklickt wird.
    Da wir ja im Menu immer das aktuell aufgeklappte Menu zeigen wollen, müssen wir ja die Information mitschleppen, was aufgeklappt ist.
    Für diesen Zweck führe ich die Variable pos mit, die sich das ganze für mich merkt.

    So, nach soviel Vorspann geht es jetzt los:
    PHP-Code:
    <?PHP
    $link 
    mysql_pconnect("localhost","wwwrun");
    $err  mysql_select_db("menusys",$link); # das sollte klar sein wir rufen unsere db an.

    # und hier kommt der code kurz aber schwer zu verstehen ...
    function baum($vater,$lpos#vater welches menu wird gezeigt ; in lpos wird meine liste aufgebaut für den nächsten klick
    {
        global 
    $link;  # Der Link zur DB durch global auch in der Funktion bekannt.
        
    global $wahl;  # hier sind als Array die ids drin die aufgeklappt sind (kommt aus der var pos)
        
    static $ebene 0# mit static erstelle ich eine Variable, die beim erneuten 
                            # Aufruf der Funktion den Wert aus der Vorgängerfunktion behält.
                            # Die ist wichtig für die Rekursion. Der Startwert ist 0 und der
                            # wird hochgezählt beim Neuaufruf. Wenn ich also im Menu bei Apfel bin,
                            # ist der Wert bei 1.

        
    $erg[$ebene] = mysql_query("SELECT * FROM `menu` WHERE `vater` = '$vater'",$link);
        
    $menge mysql_num_rows($erg[$ebene]);
        
    # Das ist auch noch klar. Lese das aktuelle Menu aus der Datenbank aus und starte eine Schleife ...
        
    for ($lo=0;$lo<$menge;$lo++) {
            
    $row mysql_fetch_row($erg[$ebene]);    # Den Menu Eintrag auslesen, in $row[1]
                                                    # ist ja der menueintrag als text ..
            
    $menu "<a href=\"baum.php3?pos=".$lpos."|".$row[0]."\">".$row[1]."</a><br>";
            
    # Hier bastel ich den Link zusammen. Am schwersten zu verstehen ist wohl
            # pos=$lpos|$row[0], ich werde noch näher darauf eingehen.

            
    if ($ebene 0) {    # Hier rücke ich einfach nur ein, je tiefer ich im Menu(Rekursion)
                                # bin, umso mehr Leerzeichen vorne dran
                
    echo str_repeat("",$ebene);
            }

            echo 
    $menu;
            if (
    $row[0] == $wahl[$ebene+1]) { # Hier folgt der Aufruf der Funktion (ab in die Rekursion)
                
    $ebene++; # ein Level hoch
                
    baum($row[0],$lpos."|$row[0]");
                
    $ebene--; # und wieder ein Level runter
            
    }
        }
    }
    Ich denke, die Rekursion ist am schwersten zu verstehen.
    Fangen wir doch mal mit pos=$lpos|$row[0] an. Wenn wir die Funktion zum erstenmal aufrufen, ist $lpos leer und $row[0] beim Menueintrag Baum = 1. Der Link sieht also so aus: baum.php3?pos=|1.
    Jetzt klicken wir mal geistig den Link.
    PHP-Code:
    $wahl explode("|",$_GET['pos']); # aus meiner pos mache ich ein array wahl - wahl[1] hat inhalt 1
    baum(0,""); # starte die Funktion, liste alles auf was als vater 0 hat 
    Wenn wir nach dem echo $menu; die Abfrage machen, haben wir beim Menupunkt Baum das:
    $row[0] - id aus der datenbank ist 1
    Ebene ist 0
    damit ist $wahl[$ebene+1] = 1 weil ja das Array über die pos Variable entspechend gefüttert wurde.
    Und somit rein in die if Abfrage:
    Weil wir ja wieder die Funktion starten, zählen wir das Level von der Rekursion eins hoch (var ebene) der erste Wert ist ja unsere id - sprich 1 - bedeutet, alles was als Vater in der db die 1 hat, wird angezeigt und die neue $lpos im neuen Aufruf bekommt den wert "|1".
    Der jetzt aufgeklappte Link vom Apfel ist so: baum?pos=|1|3
    Die "|1" kommt von der Variable lpos "|3" aus der Datenbank und ist die id vom Apfel.
    Hier ist die Variable wahl nach dem Anklicken so: wahl[1] = 1 und wahl[2] = 3.
    Der index der Variable wahl spiegelt die Rekursionstiefe wieder und der Inhalt die aufzuzeigenen Menuids
    (ich bitte um pm falls meine Erklärung zu unklar ist aber im Moment wüsste ich keine besserere Beschreibung).

    Somit steht unser Menu.
    Nur noch das angewähle im Hauptfenster des Framesets anzeigen:
    PHP-Code:
    <?php
    if (sizeof($wahl) > 1) { # nur wenn wahl vorhanden ist
        
    $id $wahl[sizeof($wahl)-1]; # den letzten Eintrag von wahl ermitteln
        # was anzuzeigen ist, aus db holen
        
    $erg mysql_query("SELECT `href` FROM `menu` WHERE `mid`='$id'",$link) or die(mysql_error());
        
    $row mysql_fetch_row($erg);
        if (
    $row[0] != "") { # wenn ein Eintrag vorhanden ist, per javascript aufrufen
    ?>
            <script language="JavaScript">
            parent.haupt.location.href="<? echo $row[0]; ?>";
            </script>
    Falls Qualm aus der Birne steigt PAUSE

    Rekursion ist auch eine der schwersten Dinge bei der Programmierung. Falls einer eine bessere Erklärung hat: melden
     


    Kommentare Kommentar schreiben

    Klicke hier, um dich anzumelden

    Was ist grün und kann quaken?