Problem mit (Baum-)Menu mittels MYSQL Tabelle
Problem mit (Baum-)Menu mittels MYSQL Tabelle
am 09.05.2005 08:15:14 von pic-as
Hallo,
ich habe folgendes Problem:
Ich hab hier ein ERP System auf Basis von MySQL und muß die
Menüstruktur nachbauen um Sie anderweitig darzustellen.
Es liegt folgende Tabelle vor:
id, parentid, name
Wobei id ein eindeutiger Index ist und parentid die id des jeweils in
der Struktur höher liegenden Eintrages angibt
Wenn parentid den Wert 0 hat, handelt es sich um einen Eintrag der
höchsten Ebene, also quasi root.
Angezeigt werden sollen immer alle Einträge aus dem root, sowie die
Einträge direkt unterhalb des jeweils ausgewählten Eintrages.
Beispieldaten:
id,parentid,name
1,0,einkauf
2,0,verkauf
3,0,lager
4,0,wareneingang
5,2,bar
6,2,rechnung
7,2,kundenkonto
8,6,bestandksunde
8,6,neukunde
daraus eribt sich folgendes menu:
+ einkauf
+ verkauf
+----- bar
+----- rechnung
+-----+----- bestandskunde
+-----+----- neukunde
+----- kundenkonto
+ lager
+ wareneingang
Beim ersten Aufruf sollen nur die Einträge einkauf,verkauf,lager und
wareneingang zu sehen sien.. das ist soweit kein Problem.
Wenn man nun auf verkauf klickt sollen zusätzlich die Einträge bar,
rechnung und kundenkonto zu sehen sein.
wenn ich auf rechnung gehe sollen die Einträge bestandskunde und
neukunde hinzukommen..
Grundsätzlich habe ich eine Website die in einem Frame das Menü
darstellt. Dieser Frame bekommt beim Aufruf die ID des angeklickten
Menüeintrages übergeben (wenn keine id übergeben wird gehe ich von
Ebene 0 aus). Anhand dieser übergebenen ID muß ich nun das Menü
aufbauen.
Wenn man einen Menüeintrag anklickt wird der frame neu geladen und
bekommt dabei die ID des angeklickten Eintrages übergeben..
Ich denke die Funktion ist jetzt klar.
Mein Problem: insgesamt hat die Menüstruktur ca 6-8 ebenen in die
Tiefe, ich muss also irgwndwie eine rekursive Auflösung machen, finde
dazu aber keinen wirklich sinnollen Ansatz.
Zusätzlich wäre es schön wenn ich zusätzlich auch noch die Ebenentiefe
des jewiligen Eintrages zurückgeliefert bekäme...
Ich denke das man hier irgendwie mit einer Funktion arbeiten könnte
die die Werte eines an sie übergebenen eintrages ausliest und als
Array zurückgibt.. und das ganze irgendwie in eine Schleife verpackt..
Aber ich komm auf keinen grünen Zweig.
Zusätzlich willl ich die Anzahl der Datenbankzugriffe so gering wie
möglich halten um das System einigermasen performant zu halten.
Danke für eure Gedankengänge hierzu
--
MCee
--> don't call it a comeback,
i've been here for years <--
Re: Problem mit (Baum-)Menu mittels MYSQL Tabelle
am 09.05.2005 14:18:50 von Patrick Daether
Mark "MCee" Pöpperl wrote:
> [...] ich muss also irgwndwie eine rekursive Auflösung machen
> [...]Zusätzlich wäre es schön wenn ich zusätzlich auch noch die Ebenentiefe
> des jewiligen Eintrages zurückgeliefert bekäme...
> [...]Zusätzlich willl ich die Anzahl der Datenbankzugriffe so gering wie
> möglich halten um das System einigermasen performant zu halten.
Hi,
ich weiß nicht, ob es für Dich in Frage kommt, das Design der DB
nochmals zu überarbeiten. Wenn ja, würde ich mal nach "Nested Set" googlen.
Die Methode ist beim Auslesen der Baumstruktur echt fix und Du kannst
recht viel sehr einfach abfragen.
Das Einfügen von Menüpunkten ist hierbei zwar nicht so performant und
trivial, aber ich schätze, dass wird ja bei der Struktur deines ERP
nicht so oft vorkommen.
Ein weiterer Vorteil ist, dass du damit auch gerichtete Bäume behandeln
kannst.
In PEAR gibt es auch schon eine Klasse, mit der Du die Zugriffe kapseln
kannst.
Gruß
Patrick
Re: Problem mit (Baum-)Menu mittels MYSQL Tabelle
am 09.05.2005 14:24:00 von do.not.REMOVETHAT
Mark "MCee" Pöpperl schrieb:
> + einkauf
> + verkauf
> +----- bar
> +----- rechnung
> +-----+----- bestandskunde
> +-----+----- neukunde
> +----- kundenkonto
> + lager
> + wareneingang
>
> Beim ersten Aufruf sollen nur die Einträge einkauf,verkauf,lager und
> wareneingang zu sehen sien.. das ist soweit kein Problem.
> Wenn man nun auf verkauf klickt sollen zusätzlich die Einträge bar,
> rechnung und kundenkonto zu sehen sein.
> wenn ich auf rechnung gehe sollen die Einträge bestandskunde und
> neukunde hinzukommen..
Also "Standard wie immer" sozusagen :-)
> Wenn man einen Menüeintrag anklickt wird der frame neu geladen und
> bekommt dabei die ID des angeklickten Eintrages übergeben..
Das ist keine gute Idee. Übergebe lieber den Pfad (z.B. "/5/9") oder
noch besser: "/verkauf/rechnung", da freut sich Google drüber.
> ich muss also irgwndwie eine rekursive Auflösung machen
Nein, Du explodest den Pfad nach "/" und baust mittels der Einzelteile
einen N-fachen Self-join zusammen.
> Zusätzlich wäre es schön wenn ich zusätzlich auch noch die Ebenentiefe
> des jewiligen Eintrages zurückgeliefert bekäme...
Den hast Du aufgrund der Anzahl der Teile im Pfad
> Zusätzlich willl ich die Anzahl der Datenbankzugriffe so gering wie
> möglich halten um das System einigermasen performant zu halten.
*Ein* simpler select liefer Dir dann genau das was Du brauchst - und im
optimalfall hast Du noch schöne, sprechende URLs mit super Keywords drinne.
Zu Nested Set: Es ist um ein vielfaches komplizierter und eigentlich nur
bei Mengenbetrachtungen so richtig sinnvoll (z.B. "wieviel
Dokumente/Nodes sind unterhalb von X?") - für Deine Aufgabenstellung ist
das eher ungeeignet.
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Problem mit (Baum-)Menu mittels MYSQL Tabelle
am 09.05.2005 14:33:53 von pic-as
Patrick Daether schrieb:
....
>Hi,
>
>ich weiß nicht, ob es für Dich in Frage kommt, das Design der DB
>nochmals zu überarbeiten. Wenn ja, würde ich mal nach "Nested Set" googlen.
>Die Methode ist beim Auslesen der Baumstruktur echt fix und Du kannst
>recht viel sehr einfach abfragen.
>Das Einfügen von Menüpunkten ist hierbei zwar nicht so performant und
>trivial, aber ich schätze, dass wird ja bei der Struktur deines ERP
>nicht so oft vorkommen.
>Ein weiterer Vorteil ist, dass du damit auch gerichtete Bäume behandeln
>kannst.
>In PEAR gibt es auch schon eine Klasse, mit der Du die Zugriffe kapseln
>kannst.
Hallo,
wenn ich einen Einfluss auf das Design hätte, würde ich sicherlich
auch ein nested set aufbauen.
Leider handelt es sich um ein bestehendes System bei dem ich lediglich
einige sachen, unter anderem die menüstruktur "visualisieren" soll.
Ich darf also auslesen soviel ich will, aber schreiben und oder
restrukturieren ist nicht..
--
MCee
--> don't call it a comeback,
i've been here for years <--
Re: Problem mit (Baum-)Menu mittels MYSQL Tabelle
am 09.05.2005 20:19:58 von Uli Honal
Matthias P. Wuerfl wrote:
> Mark "MCee" Pöpperl schrieb:
>=20
>=20
>>+ einkauf
>>+ verkauf
>>+----- bar
>>+----- rechnung
>>+-----+----- bestandskunde
>>+-----+----- neukunde
>>+----- kundenkonto
>>+ lager
>>+ wareneingang
>>
>>Beim ersten Aufruf sollen nur die Einträge einkauf,verkauf,lager und
>>wareneingang zu sehen sien.. das ist soweit kein Problem.
>>Wenn man nun auf verkauf klickt sollen zusätzlich die Einträge bar,=
>>rechnung und kundenkonto zu sehen sein.
>>wenn ich auf rechnung gehe sollen die Einträge bestandskunde und
>>neukunde hinzukommen..
>>
>>
>>Wenn man einen Menüeintrag anklickt wird der frame neu geladen und
>>bekommt dabei die ID des angeklickten Eintrages übergeben..
>=20
>=20
> Das ist keine gute Idee. Übergebe lieber den Pfad (z.B. "/5/9") oder =
> noch besser: "/verkauf/rechnung", da freut sich Google drüber.
ACK, sprechende URLs sollte man haben. Wenn man daraus den Pfad
extrahieren kann ist das schön. Aber um mit einem "deep link" ein
Element tief unten im Baum überhaupt direkt adressieren zu können, is=
t
dann erstmal n-fache Rekursion über die Tablle nötig, um den Pfad
herauszufinden. Ich denke z.B. an eine Suche über die Datenbank, deren
Ergebnisse Du verlinken möchtest.
>>Zusätzlich willl ich die Anzahl der Datenbankzugriffe so gering wie
>>möglich halten um das System einigermasen performant zu halten.
>=20
>=20
> *Ein* simpler select liefer Dir dann genau das was Du brauchst -=20
Inwiefern "simpel"? Enthält das Statement nicht mindestns n+1
self-JOINs, wenn n ist die Zahl der Ebenen ist, die Du lesen möchtest?
Und wie schreibt man das so, dass das Resultset einfach auszulesen
ist? Die Werte stehen ja dann verteilt in n Spalten, evtl. mehrfach,
oder? vgl. [1]
Was tut man, um die Blätter in der gewünschten Reigenfolge auszugeben=
?
Im Beispiel 'bar'->'rechnung'->'kundenkonto', da wird's mit einer
alphabetischen Sortierung schwierig.
> Zu Nested Set: Es ist um ein vielfaches komplizierter und eigentlich nu=
r=20
> bei Mengenbetrachtungen so richtig sinnvoll (z.B. "wieviel=20
> Dokumente/Nodes sind unterhalb von X?") - für Deine Aufgabenstellung =
ist=20
> das eher ungeeignet.
Meiner Meinung nach hat Patrick schon recht damit, Nested Sets
vorzuschlagen. Für "ungeeignet" halte ich das nicht. Begründung mit
Beispielen siehe [2].
Nested Sets scheint mir hier auf Anhieb "simpler" und performanter,
wenn man das Auslesen betrachtet. Schreib-Operationen lassen sich im
typischen Anwendungfall ohnehin an den eigenen Fingern abzählen, zur
Vereinfachung wurde ja schon die PEAR-Klasse genannt.
Vielleicht macht es sogar Sinn, eine zusätzliche Tabelle anzulegen, in
der man die Schlüssel für Nested Sets und die Ebenentiefe ablegt.
Soetwas lässt sich recht einfach aus der vorhandenen Tabelle mit
parent_ids erzeugen. [3]
viele Grüsse,
-Uli.
[1] http://phpfi.com/60145
[2] news:d57dn1$1nb$1@news01.versatel.de
[3] http://intelligententerprise.com/001020/celko.jhtml , Query #6
Re: Problem mit (Baum-)Menu mittels MYSQL Tabelle
am 10.05.2005 08:08:39 von do.not.REMOVETHAT
Uli Honal schrieb:
> Aber um mit einem "deep link" ein
> Element tief unten im Baum überhaupt direkt adressieren zu können, ist
> dann erstmal n-fache Rekursion über die Tablle nötig, um den Pfad
> herauszufinden. Ich denke z.B. an eine Suche über die Datenbank, deren
> Ergebnisse Du verlinken möchtest.
Man kann die Suchmaschine die Site per http spidern lassen (finde ich
immer eleganter) - aber wenn man das nicht macht, dann braucht man eine
Schleife - ja.
[Menü zusammenbauen]
>>*Ein* simpler select liefer Dir dann genau das was Du brauchst -
>
> Inwiefern "simpel"?
OK, streiche das "simpel". Er ist zwar leicht zu durchschauen, aber
nicht unbedingt klein.
> Enthält das Statement nicht mindestns n+1
> self-JOINs, wenn n ist die Zahl der Ebenen ist, die Du lesen möchtest?
n-1, oder? Aber egal. Du hast recht. Natürlich steigt die Komplexität
mit einem längeren Pfad. Aber dass bei theoretischen Betrachtungen das
Modell irgendwann am Ende ist wissen wir alle. Es geht darum, was in der
Praxis sinnvoll ist - und da hast Du immer eine *endliche* Anzahl Nodes.
Irgendwann wird Dir der Pfad auch zu lang....
> Und wie schreibt man das so, dass das Resultset einfach auszulesen
> ist? Die Werte stehen ja dann verteilt in n Spalten, evtl. mehrfach,
> oder?
Puh!
> vgl. [1]
Gottseidank. Ich dachte schon ich müsste tippen/suchen.
Ja, genau. Ist doch optimal. Du gehst das Ergebnis mit einer Schleife
durch und malst die Menüpunkte nacheinander hin. Du weisst von jedem
Menüpunkt den kompletten Pfad, zu welchem "Oberpunkt" er gehört und
bekommst sie alle in der richtigen Reihenfolge.
> Was tut man, um die Blätter in der gewünschten Reigenfolge auszugeben?
Man verwendet "order by" :-)
> Im Beispiel 'bar'->'rechnung'->'kundenkonto', da wird's mit einer
> alphabetischen Sortierung schwierig.
Es steht jedem frei eine beliebige Spalte zur Sortierung zu
verwenden/anzulegen.
> Meiner Meinung nach hat Patrick schon recht damit, Nested Sets
> vorzuschlagen. Für "ungeeignet" halte ich das nicht. Begründung mit
> Beispielen siehe news:d57dn1$1nb$1@news01.versatel.de.
Ha! Den Artikel kannte ich noch gar nicht :-)
Gut, IMHO gehst Du auf den (für mich) relevanten Punkt eigentlich nicht
so richtig ein: Gegeben sei die "Pfad-URL", das "Ausklapp-Menü" und ein
auch außerhalb weltbekannter Projekte real existierender Umfang.
Wie soll das so einfach mit Nested Set gehen?
Mir absolut nicht klar, wie man vertretbarem Aufwand aus "/foo/bar/baz"
das entsprechende Ausklappmenü erzeugen kann. Gegeben sind vielleicht
ein Bildschirm voll Code und ein Select mit 2 Joins - von mir aus auch 3
Selects ohne Joins. Versuche das zu toppen.
> Nested Sets scheint mir hier auf Anhieb "simpler" und performanter,
> wenn man das Auslesen betrachtet.
Mir eben - in diesem Fall - nicht.
> Schreib-Operationen
Genau. Die kommen ja auch noch dazu!
> lassen sich im
> typischen Anwendungfall ohnehin an den eigenen Fingern abzählen,
....was einen nicht davon befreit, Funktionalität dafür Bereitzustellen.
Zu toppen sind da: 5 Minuten in Access rumklicken und 5 Minuten eine
ODBC-Verbindung herstellen. ... OK. Plus 30 Minuten bei MySQL nach dem
ODBC-Treiber suchen, den finde ich nie. Das Ergebnis ist dann so
intuitiv bzw. zumindest microsoftig, dass jeder Anfänger das bedienen kann.
> zur Vereinfachung wurde ja schon die PEAR-Klasse genannt.
Seit wann ist PEAR eine *Vereinfachung*?
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Problem mit (Baum-)Menu mittels MYSQL Tabelle
am 10.05.2005 09:36:53 von Patrick Daether
Mark "MCee" Pöpperl wrote:
> Leider handelt es sich um ein bestehendes System bei dem ich lediglich
> einige sachen, unter anderem die menüstruktur "visualisieren" soll.
> Ich darf also auslesen soviel ich will, aber schreiben und oder
> restrukturieren ist nicht..
Hi,
das ist natürlich was anderes.
Kannst Du denn die Struktur einmal auslesen und in optimierter Form in
einer Session vorhalten?
Wäre jetzt auf jeden Fall mein zweiter Vorschlag.
Gruß
Patrick
Re: Problem mit (Baum-)Menu mittels MYSQL Tabelle
am 10.05.2005 15:13:04 von pic-as
Patrick Daether schrieb:
....
>Kannst Du denn die Struktur einmal auslesen und in optimierter Form in
>einer Session vorhalten?
>Wäre jetzt auf jeden Fall mein zweiter Vorschlag.
>
>Gruß
>
> Patrick
Danke für die Hilfe,
hab inzwischen selbst eine Lösung gefunden..
Mit zwei Funktionen die sich selbst aufrufen..
Außerdem brauch ich pro Session nur einen Datenbankzugriff denn ich
ziehe mir zu beginn der Session einfach alles einmal in ein Array und
arbeite dann mit dem Array weiter das ist recht fix..
--
MCee
--> don't call it a comeback,
i've been here for years <--