Hallo!
Waisen erkennen ist vermutlich nicht ganz einfach. Meiner Meinung nach kann man sie nur an ihren jüngsten und ältesten Geschwistern erkennen, denn da besteht über ihren Links- beziehungsweise Rechts-Wert eine unmittelbare Beziehung zum Elter. Ein mittleres Geschwist erkennt man nur dann als Waisen, wenn die Kette aller Geschwister mindestens in einer Richtung vollständig ist und dann der Elter fehlt. Ansonsten kann man schlecht sagen, an welcher Stelle der Baum überall Lücken hat. Die Waisen haben üblicherweise einen Großelter oder noch weiter entfernte Vorfahren. Die Links-Rechts-Werte vom Großelter und so weiter sind immer um mehr als einen Zähler außerhalb der Kind-Links-Rechts. Bei einem Elter ist das ebenfalls der Fall, wenn das Kind Geschwister hat. Eine Aussage über den nächstgelegenen Vorfahren ist noch recht einfach herauszufinden, aber nicht, in welchem Level-Abstand der sich befindet, ohne sich den gesamten lückenlosen Baum entlangzuhangeln. Vielleicht bekommt man noch irgendwelche Aussagen über gerade und ungerade Werte und andere Rechenwege, aber das will ich grad nicht weiterdenken, weil es nichts bringt. Entweder hängst du die Waisen beim nächsten Vorfahren rein oder du versuchst sie gleich ganz aus der DBMS-Ergebnismenge fernzuhalten.
Puh, ich sehe schon. Das wird nicht einfach für mich. Vermutlich ist es doch das einfachste wenn ich die Datenbankabfrage zerlege. Mist, genau das wollte ich vermeiden.
Da ich sowieso noch keine Zeit hatte deinen anderen Vorschlag zu probieren, werf ich einfach mal gut gelaunt die Abfrage in die Runde. Vielleicht kommen "wir" ja damit weiter.
Also zunächst wohl erstmal die Tabellen. Die Spalten kürze ich hier mal zugunsten der Übersichtlichkeit.
/* Menü-Namen */
CREATE TABLE `cms_menues` ( `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`))
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/* Seiten */
CREATE TABLE `cms_pages` ( `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`))
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/* Beziehung zwischen Menüs und Seiten */
CREATE TABLE `cms_menu_pages` ( `id` int(11) NOT NULL AUTO_INCREMENT,
`leftkey` int(11) NOT NULL,
`rightkey` int(11) NOT NULL,
`menu_id` int(11) NOT NULL,
`page_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `menu_id` (`menu_id`),
KEY `page_id` (`page_id`),
CONSTRAINT `cms_menu_pages_ibfk_1` FOREIGN KEY (`menu_id`) REFERENCES `cms_menues` (`id`) ON DELETE CASCADE,
CONSTRAINT `cms_menu_pages_ibfk_2` FOREIGN KEY (`page_id`) REFERENCES `cms_pages` (`id`) ON DELETE CASCADE)
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/* Benutzer */
CREATE TABLE `cms_user` ( `id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`))
ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/* Gruppen */
CREATE TABLE `cms_groups` ( `id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`))
ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/* Beziehung zwischen Benutzern und Gruppen */
CREATE TABLE `cms_user_groups` ( `id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `group_id` (`group_id`),
CONSTRAINT `cms_user_groups_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `cms_user` (`id`) ON DELETE CASCADE,
CONSTRAINT `cms_user_groups_ibfk_2` FOREIGN KEY (`group_id`) REFERENCES `cms_groups` (`id`) ON DELETE CASCADE)
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/* Inhalte */
CREATE TABLE `cms_content` ( `id` int(11) NOT NULL AUTO_INCREMENT,
`page_id` int(11) NOT NULL,
`module_id` int(11) NOT NULL,
PRIMARY KEY (`id`), KEY `page_id` (`page_id`),
KEY `module_id` (`module_id`), KEY `field` (`field`),
CONSTRAINT `cms_content_ibfk_1` FOREIGN KEY (`page_id`) REFERENCES `cms_pages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `cms_content_ibfk_2` FOREIGN KEY (`module_id`) REFERENCES `cms_modules` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/* Rechte */
CREATE TABLE `cms_rights` ( `id` int(11) NOT NULL AUTO_INCREMENT,
`table_row_id` int(11) DEFAULT NULL,
`tablefield_name` varchar(250) COLLATE utf8_bin DEFAULT NULL,
`group_id` int(11) NOT NULL,
`content_id` int(11) NOT NULL,
`rights` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `group_id` (`group_id`),
KEY `content_id` (`content_id`),
CONSTRAINT `cms_rights_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `cms_groups` (`id`) ON DELETE CASCADE,
CONSTRAINT `cms_rights_ibfk_2` FOREIGN KEY (`content_id`) REFERENCES `cms_content` (`id`) ON DELETE CASCADE)
ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
Und Abschließend die Abfrage:
SELECT
`cms_menues`.`name` AS `menuName`,
`cms_menu_pages`.`leftkey`,
`cms_menu_pages`.`rightkey`,
`cms_pages`.`id`,
`cms_pages`.`name`
FROM `cms_menu_pages`
JOIN `cms_pages`
ON `cms_menu_pages`.`page_id` = `cms_pages`.`id`
JOIN `cms_menues`
ON `cms_menu_pages`.`menu_id` = `cms_menues`.`id`
WHERE `cms_pages`.`id`
IN(
SELECT
`cms_content`.`page_id`
FROM `cms_content`
JOIN `cms_rights`
ON `cms_content`.`id` = `cms_rights`.`content_id`
WHERE `cms_content`.`page_id`
IN(
SELECT `cms_pages`.`id`
FROM `cms_menu_pages`
JOIN `cms_pages`
ON `cms_menu_pages`.`page_id` = `cms_pages`.`id`
WHERE `cms_menu_pages`.`menu_id` = ?
)
AND `cms_rights`.`group_id`
IN(
SELECT `cms_user_groups`.`group_id`
FROM `cms_user_groups`
WHERE `cms_user_groups`.`user_id` = ?
)
)
GROUP BY `cms_menu_pages`.`page_id`
ORDER BY `cms_menu_pages`.`leftKey`
Ich hoffe, dass ich nichts vergessen habe. Natürlich beantworte ich auch gern jede Rückfrage.
Zunächst einmal frage ich mich, wie ich das Problem mit den Waisen löse oder ob es einfach keine Waisen geben darf wie das anderswo gelöst wird.
Und liege ich richtig, wenn ich vermute, dass ich die Beispiele von deinem Link einfach nur in das erste, äusserste SELECT
schieben muss? Dann wäre es wohl doch einfacher als gedacht.
An den Tabellen kann ich selbst direkt nichts ändern. Es sollte aber kein Problem sein, es ändern "zu lassen" falls nötig :)
Und ob die Abfrage ideal ist, vermag ich leider auch nicht zu beurteilen.
Was meinst du, ist es sinnvoller mit der Datenbank-Abfrage oder mit dem Array zu spielen? Oder sogar mit der DB bzw. ihrer Tabellen selbst?
Oha... der post ist lang. Sorry und danke nochmals für deine Mühen!