JS-Menu aus SQL-Datenbank
von Manuel Möller



Idee und Vorbereitung

Idee

Das Menu einer Seite (wie immer es nun aussehen soll) aus ein paar Records in der Datenbank dynamisch generieren. Vorteile:

Es gibt eine globale Menu-Vorlage, aus der verschiedene Anzeigetypen generiert werden können:
z.B.
Die Vorlage für ein JavaScript-Menu mit leckeren DHTML-Effekten.
Die spartanische Variante für fanatische Links-/Lynx-/Telnetsurfer.
Eine Flash-Variante, wenn man seinen Content in Flash komplett aus der Datenbank holt.
Um daraus XML zu erzeugen, ob es nun nur cool ist oder tatsächlich einen Sinn erfüllt.
Um PDFs davon machen zu können, obwohl ich nicht weiß, wer so etwas braucht...
Wenn man einmal angefangen hat, ein Content Management System aufzusetzen und sich überlegt hat, das selbst zu schreiben und nicht irgendeine fertige Lösung aus der Dose zu nehmen - auf freshmeat.net gibt es dazu genug Quellen -, ist ein dynamisches Menü der erste - vielleicht sogar der wichtigste - Schritt. BTW: Ich wollte den Leuten, die fertige CMS benutzen, nicht auf die Füße treten, aber diese Text richtet sich auch schließlich nicht an sie.
Das Menü wird über ein Web-Frontend konfigurierbar, sehr angenehm, wenn man mal eben eine Kategorie / einen Menüpunkt hinzufügen will und gerade die ganzen Files nicht zu Hand hat.
Man kann auf diese Weise DAU-feste Interfaces schreiben, mit denen wirklich (fast) jeder in der Lage ist, ein anständig aussehendes Menü zu aktualisieren
und und und...


Unterstützte Browser

Für die JavaScript-Anzeige:

MS Internet Explorer ab Version 4 denke ich mal, ab IE5 mit Sicherheit (getestet).
Netscape 4.7 (getestet)
Netscape 6.x (getestet)
Konqueror (getestet)
Für die HTML-Version:
natürlich alle der obigen Browser
ALLE anderen Browser, die HTML anzeigen: Links, Lynx, w3m inclusive!


Warum die Arbeit?

man lernt dabei mit PHP und SQL umzugehen.
Wenn man das einmal aufgesetzt hat und es läuft, spart man sich für die Zukunft eine Menge Arbeit und mögliche Fehlerquellen.



Konkret: Der JS-Ansatz

Ich werde hier nicht auf die JavaScript-Einzelheiten eingehen, weil ich mich
(a) nicht besonders gut damit auskenne und weil sie
(b) für diesen Artikel nur eine nebensächliche Rolle spielen.

Wir haben also eins diese JS-Menüs, die man z.B. von http://www.dynamicdrive.com ziehen kann. Um ganz genau zu sein, habe ich folgendes Script, mit einigen Modifikationen benutzt: http://www.dynamicdrive.com/dynamicindex1/topnavbar.htm.

Was dieser Art von Menüs in der Regel gemeinsam ist, ist die Struktur des Files, in dem die Menüpunkte festgelegt werden.
Erst mal kommt eine Reihe von Variablen, mit denen man das Aussehen des Menüs einstellen kann; z.B. Text-/Hintergrundfarbe, Font usw.

In meinem Beispiel:

var NoOffFirstLineMenus=4; // Number of first level items
var LowBgColor='black'; // bg color when mouse is not over
var LowSubBgColor='black'; // bg color when mouse is not over on subs
var HighBgColor='black'; // bg color when mouse is over
var HighSubBgColor='black'; // bg color when mouse is over on subs
var FontLowColor='white'; // Font color when mouse is not over
var FontSubLowColor='white'; // Font color subs when mouse is not over
var FontHighColor='white'; // Font color when mouse is over
var FontSubHighColor='white'; // Font color subs when mouse is over
var BorderColor='white'; // Border color
var BorderSubColor='white'; // Border color for subs
var BorderWidth=1; // Border width
var BorderBtwnElmnts=1; // Border between elements 1 or 0
var FontFamily="arial,comic sans ms,technical"; // Font family menu items
var FontSize=9; // Font size menu items
var FontBold=1; // Bold menu items 1 or 0
var FontItalic=0; // Italic menu items 1 or 0
[...]
Auszug aus dem Config-File des JS-Menüs

Danach werden in diesem Beispiel noch vier Basisfunktionen definiert, die nicht wirklich viel machen.

function BeforeStart(){return}
function AfterBuild(){return}
function BeforeFirstOpen(){return}
function AfterCloseAll(){return}

die Funktionen

Das war es auch schon mit den Vorbereitungen. Das JS-Menü erwartet die Menüeinträge als in der folgenden Form:

1: Menu1=new Array("void main(...)","http://www.manuelm.org","",4,20,150);
2: Menu1_1=new Array("long Lebenslauf","?content=lebenslauf","",0,20,150);
3: Menu1_2=new Array("unsigned long Studium","?content=studium/studium&menu=yes","",0);
4: Menu1_3=new Array("Flash-Präsentation","http://www.manuelm.org","",0);
5: Menu1_4=new Array("char News","?content=news&menu=yes","",0);
6:
7: Menu2=new Array("char projekte(...)","http://www.manuelm.org","",6,20,125);
8: Menu2_1=new Array("Linux","?content=linux/main&menu=yes","",0,20,125);
9: Menu2_2=new Array("Kaffee-Maschine","?content=coffee/main&menu=yes","",0);
10: Menu2_3=new Array("Hitcounter","?content=stats/main&menu=yes","",0);
11: Menu2_4=new Array("Flash Spielereien","?content=portrait/main","",0);
13: Menu2_5=new Array("WAP","?content=linux/wap&menu=yes","",0);
14: Menu2_6=new Array("iKnow","?content=linux/iknow&menu=yes","",0);
15: [...]

Menüarrays



Schritt für Schritt:

1: Menu1=new Array("#angezeigter Menuname#","#link#","",#Anzahl Submenus#,#Hoehe#,#Breite#);

Menü 1

Hier wird der erste Menüeintrag (deshalb Menu1) definiert, er ist gleichzeitig die Kategorie, also der Name des Menüs, der oben ganz links angezeigt wird.
Anschießend kommen fünf wichtige Felder, in die ich hier mal die Bedeutung hineingeschrieben habe. Das sollte soweit selbsterklärend sein.
Die Anzahle der Submenüs ist einfach die Anzahl der Einträge, die im Menü sind, die wird automatisch vom PHP-Script generiert werden.
Analog wird die zweite Kategorie in Zeile 7 festgelegt. Die Leerzeile und die Einrückungen sind natürlich nicht nötig.

2: Menu1_1=new Array("Menu1 erster Menupunkt",
3: "http://www.foobar.com/der_link_dazu.html","",0,20,150);

Menü 1, Menüpunkt 1

In den Zeilen 2-5 werden jetzt nur noch die Menüeinträge festgelegt, analog für das zweite Menü in den Zeilen 8-14.

Das solls mit JavaScript erstmal gewesen sein, jetzt kommt der SQL-Teil

Die Struktur in der Datenbank

Bemerkung vorweg: bei mir heißt Menunamenummer topid und Menueintragsnummer entryid
In der Datenbank gibt es eine Tabelle, in der Menünamen und -punkte stehen. Sie sieht etwa so aus:
topid entryid Menüeintrag Link
1 0 void main(...) http://www.manuelm.org
1 1 long Lebenslauf ?content=lebenslauf"
Auszug aus der SQL-Menütabelle

Die SQL-Querys, um eine solche Tabelle zu erstellen, sehen folgendermaßen aus:

CREATE TABLE menu (
topid tinyint(4) DEFAULT '0' NOT NULL,
entryid tinyint(4) DEFAULT '0' NOT NULL,
content text NOT NULL,
link text NOT NULL
);

SQL-Befehle für Menu-Table


Das PHP-Script

Fehlt also nur noch das Script, mit dem die Arrays für das JavaScript-Menü erzeugt werden. Die ganzen Variablen können einfach so aus einer statischen Textdatei mit include() geholt werden.

Dann sollte man den Link zur Datenbank mal aufmachen: 1: $host = >dbhost<

2: $user = >dbuser<
3: $password = >dbpwd<
4: $db = >your database<
5: $menutable = >name of table with menu entries<
6: $link = mysql_connect ($host, $user, $password)
7: or exit(-1);


Link zur DB aufmachen

Wichtig ist, daß das Script erstmal erkennen muß, wie viele Einträge es unter einer Kategorie gibt, schließlich muß das ja angegeben werden. Die ganze Tabelle wird deshalb für jedes Menü durchiteriert, wobei ich davon ausgehe, daß es unter einer Kategorie nur Menüpunkte gibt und nicht auch noch Unterkategorien, was das JS hergibt, mich aber nicht interessiert hat.
Erstmal das Script im Überblick:

0: [...]
1: $query = "SELECT max(topid) FROM menu";
2:
3: $result = mysql_db_query($db,$query)
4: or die("Fehler beim SELECT: <b>$query</b>");
6:
7: $row2=mysql_fetch_array($result);
8:
9: for ($i=1;$i<($row2[0]+1);$i++)
10: {
11: $query ="SELECT * FROM $menutable WHERE (topid = "".$i."") ORDER by entryid";
12: $result = mysql_db_query($db,$query)
13: or die("Fehler beim SELECT2:<b>$query</b>");
14: while ($row = mysql_fetch_array($result))
15: {
16: if ($row['entryid'] == 0)
17: {
18: /* Menu-Name */
19: $query2 ="SELECT topid FROM $menutable WHERE (topid = "".$i."")";
20: $num_entries = mysql_num_rows(mysql_db_query($db,$query2))
21: or die("Fehler beim SELECT: <b>$query</b>");
22: echo "nMenu".$i."=new Array("".$row['content']."","".$row['link'];
23: echo "&menu=1","",".($num_entries - 1).",20,150);n";
24: }
25: else
26: {
27: /* Menu-Einträge */
28: echo "Menu".$i."_".$row['entryid']."=new Array("".$row['content']."","";
29: echo $row['link']."&menu=1","",0,20,150);n";
30: }
31: }
32: }
33: [...]

Der Algorithmus, um das Menü zu erzeugen

Vorher mache ich natürlich noch die Verbindung zur Datenbank auf. Das vollständige Script stelle ich unten bei den Links zur Verfügung.

Was dieser Teil macht:
Der Query, der die Anzahl von Kategorien zurückliefert:

1: $query = "SELECT max(topid) FROM menu";

Hier wird der Query ausführt, und das Ergebnis geholt: 3: $result = mysql_db_query($db,$query)
4: or die("Fehler beim SELECT: <b>$query</b>");
6:
7: $row2=mysql_fetch_array($result);

Jetzt startet die erste Schleife, die die Kategorien durchiteriert:
9: for ($i=1;$i<($row2[0]+1);$i++)

In $row2[0] steht die Anzahl der Kategorien drin, die wir eben geholt haben.

Nun die Kategorienamen holen. Sie sind dadurch definiert, daß ihre EntryID == 0 ist (Zeile 16):

11: $query ="SELECT * FROM $menutable WHERE (topid = "".$i."") ORDER by entryid";
12: $result = mysql_db_query($db,$query)
13: or die("Fehler beim SELECT2:<b>$query</b>");
14: while ($row = mysql_fetch_array($result))
15: {
16: if ($row['entryid'] == 0)
17: {
18: /* Menu-Name */
19: $query2 ="SELECT topid FROM $menutable WHERE (topid = "".$i."")";
20: $num_entries = mysql_num_rows(mysql_db_query($db,$query2))
21: or die("Fehler beim SELECT: <b>$query</b>");
22: echo "nMenu".$i."=new Array("".$row['content']."","".$row['link'];
23: echo "&menu=1","",".($num_entries - 1).",20,150);n";


Wenn die EntryID != 0 ist, muß es ein Menüeintrag sein, er wird über die TopID dem jeweiligen Menü zugeordnet:

25: else
26: {
27: /* Menu-Einträge */
28: echo "Menu".$i."_".$row['entryid']."=new Array("".$row['content']."","";
29: echo $row['link']."&menu=1","",0,20,150);n";
30: }

wieder nur billiges iteratives "Abgrasen" der Einträge!

Wie leicht zu erkennen ist, sind bei mir Breite und Höhe der Menüfelder immer fest auf 20 bzw. 150 Pixel eingestellt. Wer will, kann auch das noch als Feld in der Datenbank speichern. Bei mir sind alle Menüfelder gleich groß.



Das war es schon fast!

Ein paar Sachen fehlen aber noch:

1.: Script-Header:

echo "<script type='text/javascript'>n";
echo " function Go(){return}n";
echo "</script>n";
echo "<script type='text/javascript'>n";

2.: Die Variablen müssen ja noch aus dem statischen File inkludiert werden (s.o):

include('js/variables.js');

bei mir liegt das File offensichtlich im Verzeichnis js/"


Schmankerl: HTML-Version für deaktiviertes JS

Bis jetzt hat das ganze ja eigentlich nur Arbeit gemacht. Jetzt kommt ein Teil, der Arbeit erspart.

Da die Menüstruktur ohnehin unabhängig von der Formatierung vorliegt, läßt sich jetzt mühelos eine pure HTML-Version daraus erstellen. Ich habe hier als Beispiel mal die genommen, die ich auf meiner Seite einsetze.
Wie man das HTML-Menü nun aber formatiert, bleibt jedem selbst überlassen.

Hier also der Quellcode meiner Version:

1: //Textmenu
2: $link = mysql_connect ($host, $user, $password)
3: or exit(-1);
4: $query = "SELECT max(topid) FROM menu";
5: $result = mysql_db_query($db,$query)
6: or die("Fehler beim SELECT1: <b>$query</b>");
7: $row2=mysql_fetch_array($result);
8: echo "<center><table border="0"><tr>n";
9: for ($i=1;$i<($row2[0]+1);$i++)
10: {
11: $query ="SELECT * FROM $menutable WHERE (topid = "".$i."") ORDER by entryid";
12: $result = mysql_db_query($db,$query)
13: or die("Fehler beim SELECT: <b>$query</b>");
14: echo "<td valign="top">n";
15: while ($row = mysql_fetch_array($result))
16: {
17: if ($row['entryid'] == 0)
18: {
19: //Menu-Name
20: $query2 ="SELECT topid FROM $menutable WHERE (topid = "".$i."")";
21: $num_entries = mysql_num_rows(mysql_db_query($db,$query2))
22: or die("Fehler beim SELECT: <b>$query</b>");
23: echo "<b><a href="".$row['link']."">".$row['content']."</a></b><br>n";
24: }
25: else
26: {
27: //Menu-Einträge
28: echo "<a href="".$row['link']."">".$row['content']."</a><br>n";
29: }
30: }
31: echo "</td>n";
32: }
33: echo "</tr>n</table></center>n";

Scriptabschnitt für die HTML-Version

In diesen Zeilen passiert praktisch das gleiche, wie in den vorher eingehend beschriebenen für die Erzeugung der JavaScript-Arrays, nur daß diesmal die gleichen Informationen als HTML formatiert ausgegeben werden.


Erweiterungen

Wie in der Einleitung angedeutet, ist auch es auf diese Weise leicht, aus dem Tabelleninhalt XML zu erzeugen und umgekehrt.

Auch WML geht, zumal man da gleich die Links auf die passenden Decks setzen kann.

Den Kram in ein Flashmenü zu packen geht jetzt auch einfach, entweder über den XML-"Umweg" oder direkt.

Wenn man ohnehin erfaßt, ob die Clients der Seite JS aktiviert haben, kann man ihnen "automagisch" die HTML-Alternative geben.

Ein Frontend zu programmieren, ist jetzt auch kein Problem mehr. Realisieren könnte man das in PHP, um das Menü im Browser ändern zu können, aber auch eine Variante, die direkt auf die DB zugreift - wenn der Provider das erlaubt - ist möglich.



Links / Impressum

Der Verfasser übernimmt keine Haftung für irgendwelche Aktionen, die durch diesen Text ausgelöst werden.
Vervielfältigung & Verbreitung einer veränderten Version nur mit ausdrücklicher Erlaubnis des Verfassers.
Änderungen vorbehalten.


als Beispiel, wie das aussehen kann (http://www.manuelm.org/)


The PHP Layers Menu: es gibt Leute, die das wesentlich perfekter umgesetzt haben! (http://phplayersmenu.sourceforge.net/index.php3)


auch diese Menü könnte man nehmen (http://www.dynamicdrive.com/dynamicindex1/topnavbar.htm)


http://www.dynamicdrive.com, dort gibt es Massen von JS (http://www.dynamicdrive.com/)




Softwareentwicklung Hamburg - Partyboot Frankfurt - Hochzeitsauto mieten - Autoversicherung CONTECTA Detektei Hamburg

© 2000-2016 SAP® SRM Beratung - 2bits GmbH