Moin!
Was ich da komisch finde:
- Eine Seite gehört zu mehreren Modulen? Hängt natürlich davon ab, was für dich "Seite" ist, aber ich würde das nicht so machen. Eine Seite sollte immer genau zu EINEM Modul gehören.
Wieso sollte das so sein? Ich könnte z.B. eine Seite haben auf der die Module "Login" und "News" sind. Auf der nächsten Seite habe ich dann "Login" und "Artikel" usw. Deshalb diese Tabellen-Verknüpfung. Ist das denn so schlecht? Wie sollte ich die beiden Module als 1 Modul in die Seite fügen?
Ok, wenn du das so herum siehst, dann gehören eben mehrere Module zu einer Seite, und die Seite ist das bestimmende Element.
Was nicht sein sollte: Dass ein Modul mehrere Seiten hat, und auf jeder Seite wieder mehrere Module, die wieder mehrere Seiten ... Du erkennst das Problem? Deine Struktur erlaubt beliebig tiefes verschachteln von Modulen mit Seiten mit Modulen mit Seiten. Und nur durch die Tatsache, dass "Seite" ein Element ist, was sich in der Realität nicht selbst enthalten kann, wird die Sinnlosigkeit dieser Strukturmöglichkeit erst deutlich.
Wenn du Obermodule für mehrere Seiten und Untermodule als Element auf einer Seite haben willst, dann benenne nicht beides "Module" und verwalte nicht beides in derselben Tabelle.
Grundsätzlich würde ich die einem User zugeordneten Gruppen immer mit in die Session ziehen, denn Zugriffsrechte orientieren sich an der Gruppe, nicht am User.
Was meinst du mit "mit in die Session ziehen"? Ansonsten ist das auch der Plan, dass die Zugriffsrechts von den Gruppen bezogen werden.
Wenn ein User sich angemeldet hat, dann kennst du seine User-ID in der Session. Schreib seine Gruppen auch noch hinein, das vereinfach dir die Prüfung der Zugriffsrechte.
Also fange ich bei table.rel_groups_user mit der Abfrage an dann ein join in table.groups.
Nein, die Gruppentabelle bringt dich ja nicht weiter, die ist ja der Endpunkt für die Gruppen-ID.
Du verknüpfst direkt mit table.groups_module und kriegst dann Modul-IDs - und von dort geht es zu den Seiten.
Wie erwähnt: Die Endtabellen, in denen die Foreign-IDs definiert werden, joinst du nur hinzu, wenn dich die Detailinfos zu der jeweiligen ID auch interessieren.
Aber wie frage ich ab ob ein Modul für die Gruppe(n) und Seite zur Verfügung steht. Ich weiß nicht wie ich die Tabelle table.rel_modules_pages weglassen kann. Siehe oben.
Wenn du strukturierst, dass Module und Seiten nur eine 1:n-Beziehung haben, dann entfällt diese Tabelle, und du fügst der Seitentabelle eine Spalte "modul-id" hinzu.
Das ist die klassische Vorgehensweise für 1:n-Beziehungen. :)
Um nochmal auf die Frage zurück zu kommen, wieso können die Tabellen inkonsistent werden bzw. wie wird durch welche ungeschickten Datensätze was ausgeschlossen?
Du kannst sagen: Zur Gruppe 1 gehört Modul 1, und zur Gruppe 1 gehört Seite 1. Dir fehlt jetzt aber die Verknüpfung "Seite 1 gehört zu Modul 1".
Wenn du die Berechtigung durchgehst:
Ein User der Gruppe 1 will die Seite 1 ansehen: Darf er das? Was sieht er da? Modul 1? Das gehört zu seiner Gruppe, aber nicht zur Seite 1.
Außerdem kann man definieren: Zur Gruppe 2 gehört Modul 2, und zu Modul 2 gehört Seite 2.
Ein User der Gruppe 2 will Seite 2 ansehen. Er darf Modul 2 sehen, und Modul 2 verknüpft Seite 2 - aber Gruppe 2 hat keine direkte Verbindung zu Seite 2. Ist das jetzt erlaubt?
Die dritte Definitionsmöglichkeit: Zur Gruppe 3 gehört Seite 3, und zur Seite 3 gehört Modul 3.
Ein User der Gruppe 3 will Seite 3 ansehen. Darf er das, weil Seite 3 zwar Modul 3 verbindet, aber Modul 3 nicht zu Gruppe 3 gehört?
Wie du siehst, erlaubt dein "Ring" bzw. Dreieck der Tabellenverknüpfung, dass zwar ein logischer Zusammenhang zwischen den drei Tabellen Gruppe, Seite und Modul hergestellt wird, aber man kann jede der drei Dreiecks-Seiten offenlassen, und erhält dann schwierig zu beantwortende Fragen, wie solch ein "offener Ring" zu interpretieren ist. Die fehlende Verknüpfung ist jeweils das Problem: Wie ist sie zu schließen.
Außerdem sind überzählige Verknüpfungen das Problem: So ein Ring hat eben nicht automatisch nur eine einzige logische Verknüpfung, die den Ring schließt, sondern rein von den möglichen Werten in der DB ist jede beliebige Verknüpfung möglich: Du kannst (Fall 1) eben auch von Modul 1 eine Verknüpfung zu Seite 3 machen. Welche Auswirkung hat das?
Wenn du tatsächlich auf der gemeinsamen Verknüpfung von Seiten, Modulen und Gruppen bestehst, dann verknüpfe alle drei Werte nur in einer einzigen Tabelle!
Dann siehst du auch sofort offensichtliche Definitionslücken, bzw. kannst durch NULL-Spalten sowas wie Joker (Gilt für alles) implementieren.
Nur kurz Skizziert: Das Loginmodul 1 soll auf allen Seiten (*) erscheinen, aber nur für die Gruppe nichtangemeldeter User (1):
modul - seite - gruppe
1 NULL 1
Das Wetter-Modul (2) soll auf allen Seiten erscheinen, aber nur für reguläre User (Gruppe 2) und Admins (Gruppe 3)
2 NULL 2
2 NULL 3
Das IP-Info-Modul (3) soll nur auf der Netzwerkseite (1) erscheinen, aber für alle Gruppen:
3 1 NULL
Alternativ, weil die Möglichkeit "alle Gruppen" eventuell zu hohes Risiko bedeutet, müsstest du für jede Gruppe einen Eintrag machen:
3 1 1
3 1 2
3 1 3
Du ersetzt deine drei Tabellen, die jeweils nur zwei Tabellen verknüpfen, also durch eine einzige Tabelle, die drei Tabellen verknüpft. Und ein Eintrag in dieser Tabelle ist automatisch konsistent, weil er eindeutig alle drei Tabellen verknüpft (oder durch NULL eben "alles" gemeint sein kann, wenn die Applikation das so will).
Bedenke, dass auf die drei Spalten zwar ein übergreifender Unique-Key gesetzt werden kann, bei NULL-fähigen Spalten darin aber keine Uniqueness mehr garantiert wird in MySQL - works as designed im Hinblick auf die Bedeutung von NULL. NULL != NULL für alle Werte von NULL, deshalb ist das Tupen "1-2-NULL" ungleich "1-2-NULL" im unique index.
- Sven Rautenberg