Symfony-Framework; idiomatische Möglichkeit, die Rolle eines Benutzers zu speichern

8

In meiner Symfony 2-Anwendung möchte ich das Standardautorisierungssystem von Benutzern und Rollen verwenden (http://symfony.com/doc/2.0/book/security.html)

Mein Benutzer ist eine Entität, die in einer Datenbank mit Doktrin (implementierende Benutzeroberfläche) gespeichert ist. Ich werde 5 vordefinierte Rollen in meinem System haben, wobei jeder Benutzer möglicherweise mehrere dieser Rollen hat.

Was wäre die idiomatische Art, dies umzusetzen? Ich denke an die folgenden drei Lösungen.

  1. Erstellen Sie eine separate Rolle-Entität und erstellen Sie eine Viele-zu-viele-Beziehung mit der Benutzerentität

    • Plus: Einfach alle Benutzer mit einer bestimmten Rolle zu bekommen
    • Con: Ressourcenintensiv? (Sie benötigen immer einen doppelten Join, um alle Rollen für einen Benutzer abzurufen)
    • Con: Nicht idomatisch? Die Anzahl der Rollen (und deren Namen) ändert sich nie, macht es also Sinn, sie in der Datenbank als separate Einheit zu speichern?
  2. Haben Sie ein Feld innerhalb des Benutzers, das eine sortierte, durch Kommata getrennte Liste von Rollen ist, und getRoles () wird als explode(',',this.all_roles)

    implementiert
    • Plus: Nicht rechenintensiv
    • Con: Schwer, alle Benutzer mit einer bestimmten Rolle
    • zu bekommen
    • Con: Datenbankfelder wie diese lassen Kätzchen weinen (normalization und stuff)
  3. Haben Sie 5 binäre Felder in der Benutzerentität für jede Rolle

    • Plus: Nicht rechenintensiv
    • Plus: Einfach alle Benutzer mit einer bestimmten Rolle zu bekommen
    • Con: Das fühlt sich immer noch nicht gut an

Was ist die idiomatische Art, dieses System zu implementieren?

    
Peter Smit 06.03.2012, 12:06
quelle

1 Antwort

12

Natürlich hängt eine Antwort sehr von Ihren Anforderungen ab, aber ich werde versuchen, sie so global wie möglich zu beantworten.

Option 1: Der relationale Weg

Aus rein relationaler Sicht möchten Sie, dass Ihre Datenbank normalisiert wird, was zu Ihrer ersten Option führen würde: Eine Tabelle für die Rollen mit einer m: n-Beziehung zu Ihrer Benutzertabelle. Dies hat einige Vorteile:

  • Nun, es ist die Art und Weise, wie man erwarten würde, dass Ihre Datenbank funktioniert, also keine Funktionalität, die in Ihren Entitäten versteckt ist.
  • Keine Möglichkeit, Dinge zu vermasseln (wie wenn Sie ein Varchar-Feld haben und erwarten, dass es ein Format wie Koma-Trennung hat)
  • Nur eine Möglichkeit, Dinge zu tun

In Bezug auf Ihre Bedenken, dass sich Rollen niemals ändern: Bei der Speicherung relationaler Daten geht es nicht darum, wie oft sie sich ändert. Und man sollte immer daran denken, dass sich die Anforderungen ändern. Je mehr Sie im Namen der Optimierung durcheinander bringen, desto mehr kämpfen Sie später, wenn mehr Rollen erforderlich sind, die sich öfter ändern.

Natürlich können Sie Probleme mit der Performance haben, besonders wenn Sie auf ein Problem beim Ladevorgang stoßen oder wenn Sie die Dinge nicht zwischenspeichern und die Rollen bei jedem Laden der Seite neu laden müssen. Aber wiederum sind relationale Datenbanken darauf ausgelegt, solche Dinge zu unterstützen. Daher sollten hier Möglichkeiten zur Optimierung der Abfragen bestehen.

Option 2: Der Hack

Ihre zweite Option, einfach alle Rollen in einem Varchar zu speichern, wäre in Bezug auf die Leistung viel schöner. Nur ein Textfeld zum Laden, etwas PHP-Verarbeitung und fertig. Auf der anderen Seite können Sie auf mehrere Probleme stoßen:

  • Sie haben keine Kontrolle über das varchar-Feld, so dass ein Fehlfunktionsskript Ihre gesamte Anwendung kompromittieren kann (Das ist wirklich schlimm, aber abhängig von Ihrem Projekt, wenn Sie der einzige Entwickler sind und Sie wissen, was Sie tun, könnte es gehen gut)
  • Eine Aktualisierung auf ein Dataset ist viel schwieriger, da Sie alle Rollen extrahieren, die fraglichen aktualisieren und zurückspeichern müssen
  • Die Abfrage für alle Benutzer mit einer bestimmten Rolle ist viel schwieriger
  • Das Löschen einer Rolle ist viel schwieriger

Option 3: Die pragmatische Lösung

Die dritte Option mit 5 booleans für jede Rolle ist in der Mitte: Es gibt keine Möglichkeit, es zu vermasseln und die Leistung sollte kein Problem sein. Das Aktualisieren ist ebenso einfach wie das Löschen einer Rolle oder das Hinzufügen einer neuen Rolle. Es ist ziemlich klar, was die Felder machen, also auch nicht auf dieser Seite. Es macht Ihre Entität und Datenbank ein wenig hässlicher und Sie hätten die Rollennamen in Ihrem Benutzermodell, um die Wahr / Falsch-Felder den richtigen Rollennamen zuzuordnen, was etwas verwirrend sein könnte.

Ergebnis

Dies alles im Kopf, würde ich mit Option 1 gehen. Man kann annehmen, dass Leistung ein Problem ist, aber wenn ich das nicht bewiesen habe, denke ich nicht über solche Sachen nach. Am Ende, was machst du, wenn du wirklich ein echtes Performance-Problem hast? Sie können einige zusätzliche Hardware hinzufügen, Ihre dbms optimieren, die Abfragen optimieren oder vielleicht ein dbms mit mehr Performance-Build verwenden (Hello Oracle!).

Sie können die Option 3 immer später verwenden, wenn Sie aufgrund der Rollentabelle beweisen, dass Ihre Anwendung langsam ist. Sie müssten nur Ihre Benutzereinheit ändern und eine Abfrage haben, die die Rollen extrahiert und die richtigen Wahr / Falsch-Kombinationen für jeden Benutzer einstellt. Wenn die Software sauber ist, ist dies ein Problem von Stunden, also müssen Sie es jetzt nicht mit der Vorstellung machen, dass die Leistung schlecht sein könnte.

    
Sgoettschkes 11.03.2012, 11:58
quelle