Ich erstelle ein Menüsystem in PHP und MySQL. Ich werde verschiedene Menüs haben und mit jedem Menü wird eine Reihe von Menüpunkten verbunden sein.
Auf der Site habe ich auch unterschiedliche Benutzerberechtigungen, einige Benutzer können alle Menüelemente sehen und einige Elemente sind für einige Benutzer ausgeblendet. Ich bin gespannt, wie ich mit den Berechtigungen auf saubere Weise umgehen kann, damit in Zukunft problemlos mehr Benutzertypen hinzugefügt werden können.
Was ich bisher habe, ist ungefähr so:
-------------------
|Menus
-------------------
|id| |display name|
-------------------
----------------------------------------------------------
|Menu items
----------------------------------------------------------
|id| |menu_id| |label| |link| |parent| |sort| |permission|
----------------------------------------------------------
Ich denke, dass die permission
Spalte entweder eine durch Kommas getrennte Zeichenfolge sein kann, die ich mit der Berechtigungs-ID des aktuellen Benutzers vergleichen kann. Es könnte auch ein Verweis auf eine andere Tabelle sein, die alle möglichen Kombinationen der derzeit vorhandenen Berechtigungen definiert.
Eine Lösung könnte auch darin bestehen, einfach mehrere Menüelemente zu speichern, wobei der einzige Unterschied die Berechtigung ist, obwohl dies zu einer doppelten Speicherung und möglicherweise zu einer Verwaltung führen würde.
Ich würde gerne einige Gedanken darüber hören, wie man dies strukturiert und was als sauber, dynamisch und beschissen angesehen werden kann.
Vielen Dank.
quelle
Antworten:
Ich werde es anhand eines ER-Diagramms modellieren.
PERMISSION
ist der Zugriff, der einemROLE
auf einen bestimmten gewährt wirdMENU_ITEM
.USER
kann viele ROLLEN erhalten.Dann können Sie eine Ansicht erstellen, damit Sie die Verknüpfungen nicht jedes Mal schreiben müssen:
Jedes Mal, wenn Sie wissen möchten, auf welche Menüelemente ein Benutzer Zugriff hat, können Sie diese abfragen:
BEARBEITEN:
Da einem Benutzer mehrere Rollen zugewiesen werden können, können sich die Berechtigungen der Rollen überschneiden, dh zwei unterschiedliche Rollen können auf denselben Menüpunkt zugreifen. Wenn Sie eine Rolle definieren, wissen Sie vorher nicht, ob sie einige Berechtigungen mit anderen Rollen gemeinsam hat. Da es sich jedoch um die Vereinigung von Mengen handelt, ist es nur wichtig, ob eine bestimmte Berechtigung Teil der Menge ist oder nicht, und nicht, wie oft sie erscheint, daher die
distinct
Klausel in der Ansicht.quelle
Wenn Sie eine durch Kommas getrennte Liste haben, müssen Sie jedes Mal einen Teilstring-Vergleich durchführen, wenn Sie eine Abfrage für das Menü durchführen. Das ist weniger als ideal.
Sie müssen die Tabelle normalisieren:
Wenn Sie immer noch die durch Kommata getrennte Liste (aus irgendeinem Grund) möchten, können Sie es mit Dingen wie herausziehen
group_concat
in MySQLwm_concat
in Oracle oder ähnliche Funktionen in anderen Sprachen.Der Vorteil hierfür ist vielfältig.
Erstens gibt es die Praktikabilität des Anrufs. Wenn Sie einen Teilstring für eine beliebig große Zeichenfolge ausführen (wenn Sie die Größe festlegen, können Sie später Probleme beim Auffüllen der Zeichenfolge haben, sodass Sie Berechtigungen erhalten, wie
a
stattanother_permission
), müssen Sie die Zeichenfolge in jeder Zeile scannen. Dafür sind Datenbanken nicht optimiert.Zweitens wird die Abfrage, die Sie schreiben, viel einfacher. Um festzustellen, ob die Berechtigung 'foo' in einer durch Kommas getrennten Liste vorhanden ist, müssen Sie nach 'foo' suchen.
Dies ergibt jedoch ein falsches Positiv, wenn Sie auch die Erlaubnis 'foobar' haben. Jetzt müssen Sie also einen Test wie haben
Dies gibt jedoch ein falsches Negativ aus, wenn sich 'foo' am Anfang oder Ende der Zeichenfolge befindet. Das führt zu so etwas
Sie werden feststellen, dass es sehr wahrscheinlich ist, dass Sie mehrere Scans der Zeichenfolge durchführen müssen. Dieser Weg führt zum Wahnsinn.
Beachten Sie, dass Ihnen bei all diesen die praktische Fähigkeit zur Parameterbindung fehlt (immer noch möglich, wird nur noch hässlicher).
Durch die Normalisierung des Feldes erhalten Sie eine viel größere Flexibilität und Lesbarkeit in Ihrer Datenbank. Du wirst es nicht bereuen.
quelle
Dieser klassische Ansatz dazu ist
User -> UserGroup
und wird dann mit a verbundenMenu -> MenuItem -> UserGroup
. Verwenden eines ganzzahligen Werts zum Abwägen der Berechtigungsstufe.Wenn Sie ein Menü für den aktuellen Benutzer anzeigen müssen. Sie können die Datenbank folgendermaßen abfragen.
Dadurch werden nur Menüs ausgewählt, die für den aktuellen Benutzer basierend auf der Bedingung für sichtbar sind
option1
.Wenn Sie alternativ die Gruppendetails des aktuellen Benutzers in der aktuellen Sitzung speichern, ist kein Join erforderlich.
Wenn Sie darüber sprechen, mehrere Berechtigungen pro Menüelement speichern zu wollen. Ich würde darauf achten, Benutzerrollen und Geschäftslogik nicht zu verwechseln.
quelle