Da hier mehrfach die Frage nach dem Auf- und Zuklappen gestellt wurde möchte ich an dieser Stelle mal meine Lösung vorstellen.
Zusätzlich zu lft und rgt speichere ich schon beim hinzufügen der Menüpunkte die parent_id, also die id des Elternelements ab. Alle Elemente mit der gleichen parent_id wie der angeklickte Menüpunkt sind also Geschwister und müssen mit angezeigt werden. Des weiteren sind alle Menüpunkte anzuzeigen, die die id des aktuellen Menüpunktes als parent_id eingetragen haben, sprich die Kinder. Das funktioniert dann für Menüs mit nur einer Unterebene. Will man mehr Ebenen verarbeiten werden damit aber nicht die alle Kinder der Großeltern angezeigt (Ich mag diese Vergleiche ;-) ).
Als Beispiel folgende Struktur:
PHP-Code:
root
---Punkt 1
---Punkt 2
------Punkt 2.1
---------Punkt 2.1.1
---------Punkt 2.1.2
------------Punkt 2.1.2.1
------------Punkt 2.1.2.2
------------Punkt 2.1.2.3
------------Punkt 2.1.2.4
---------Punkt 2.1.3
------Punkt 2.2
---------Punkt 2.2.1
---------Punkt 2.2.2
------Punkt 2.3
---Punkt 3
------Punkt 3.1
Wenn Punkt 2.1.2 angeklickt wurde haben 2.1.1 und 2.1.3 die gleiche parent_id und werden mit angezeigt (nicht aber die Unterelemente, da diese eine andere parent_id haben). Ausserdem haben 2.1.2.1 bis 2.1.2.4 die id des Angeklickten als parent_id, werden also ebenfalls angezeigt. Level 1 Elemente werden einfach immer angezeigt, womit wir auch Punkt 1, Punkt 2 und Punkt 3 haben. Aber was nun noch fehlt ist Punkt 2.2 und 2.3.
Daher habe ich vorher mit folgender Abfrage "alle Eltern" ausgelesen:
PHP-Code:
$query = '
SELECT
m2.parent_id
FROM
menupunkte AS m1
LEFT JOIN
menupunkte AS m2
ON
m1.lft BETWEEN m2.lft AND m2.rgt
AND
m1.rgt BETWEEN m2.lft AND m2.rgt
WHERE
m1.id='.$id_aktueller_Punkt.'
AND
m2.parent_id!=0 // Hier schließe ich die Wurzel aus
AND
m2.parent_id!=1 // Hier alle Level 1 Elemente, die sind ja eh immer da
;';
Als Ergebnis würde ich für obigen Baum mit Auswahl von 2.1.2 die parent_id von 2.1 geliefert bekommen. Ich packe also das Ergebnis in ein Array ($parents), um es später zu verwenden.
Der Sinn ist dass ich nun zusätzlich noch alle Elemente auslesen kann, die die gleiche parent_id wie meine direkten Vorfahren haben. Also Punkt 2.2 und 2.3.
Ich bekomme demnach folgendes Menü:
PHP-Code:
root
---Punkt 1
---Punkt 2
------Punkt 2.1
---------Punkt 2.1.1
---------[b]Punkt 2.1.2[/b]
------------Punkt 2.1.2.1
------------Punkt 2.1.2.2
------------Punkt 2.1.2.3
------------Punkt 2.1.2.4
---------Punkt 2.1.3
------Punkt 2.2
------Punkt 2.3
---Punkt 3
Die letztendliche Abfrage bau ich mir dann so zusammen:
PHP-Code:
// Menüpunkte auslesen
$query = 'SELECT
/* Daten */
COUNT(*) AS level,
COUNT(*)-1 AS open
FROM
menupunkte AS m1,
menupunkte AS m2
WHERE
m1.lft BETWEEN m2.lft AND m2.rgt
AND
m2.lft!=1 // Schließt bei mir die Wurzel aus
GROUP BY
m1.lft,
m1.parent_id, // damit parent_id in HAVING
m1.id // auftauchen darf
HAVING
COUNT(*)=1 // Level 1 Elemente
OR m1.parent_id=m1.id // Ähm?
OR m1.parent_id='.$itm; // Kinder
// Vorfahren mit auswählen
if(count($parents)>0) {
foreach($parents AS $parent) {
$query .= ' OR m1.parent_id='.$parent;
};
};
$query .='
ORDER BY
m1.lft
;';
Bei mir klappt das ganze so ausgezeichnet und ohne JS.
level ist bei mir übrigens die Ebene. Die oberste Ebene hat bei mir die 1. Die Zweite Ebene die 2 usw (logisch!). Wenn ich von der Ebene nun 1 abziehe (COUNT(*)-1) haben alle ausgeklappten Elemente einen Wert größer 0 und sind damit logisch wahr. Dies kann man dann für eine CSS-Formatierung nutzen. So haben alle Level 1 Elemente bei mir die Formatierung border-top:1px solid #333333 und alle ausgeklappten Elemente nicht. Somit kann man die Zusammengehörigkeit gut darstellen.
Ich hoffe das hilft manch einem weiter...
Gruß, toby