So verwenden Sie UniqueEntity sicher (auf Websites mit mehr als einem gleichzeitigen Benutzer)

8

Kann jemand clever das Entwurfsmuster teilen, das verwendet wird, um dieses grundlegende und gemeinsame Nebenläufigkeitsproblem in Doctrine \ Symfony zu vermeiden?

Szenario: Jeder Benutzer muss einen eindeutigen Benutzernamen haben.

Fehlgeschlagene Lösung:

Warum es scheitert: Zwischen dem Überprüfen und Fortbestehen des Benutzers kann der Benutzername von einem anderen Benutzer verwendet werden. Wenn dies der Fall ist, löst Doctrine eine UniqueConstraintViolationException aus, wenn versucht wird, den neuesten Benutzer zu erhalten.

    
Jeff Clemens 25.11.2016, 00:21
quelle

4 Antworten

2

Hier ist meine Antwort:

  • Es werden Fehler angezeigt, wenn der Constraint-Verstoß auftritt, etwa wenn der Validator den Constraint-Fehler behandelt,

  • Es verhindert, dass Datenbank-Updates, die nicht "protected" sind, Ihre Steuerungslogik durchbrechen (z. B. mit einer UPDATE-Anweisung oder einer Formularübergabe mit "ungeschützt" ) Controller),

  • Es ist eine datenbankunabhängige Lösung.

Hier ist der Code mit Erläuterungen zu Kommentaren:

%Vor%     
Jules Lamur 02.12.2016, 01:20
quelle
1

Eine Möglichkeit, um zu erreichen, was Sie wollen, ist das Sperren mit der Symfony LockHandler .

Hier ist ein einfaches Beispiel, das das Muster verwendet, auf das Sie sich in Ihrer Frage beziehen:

%Vor%

Hinweis: Dies funktioniert nicht, wenn Sie Ihre Anwendung auf mehreren Hosts ausführen, aus der Dokumentation:

  

Der Sperrhandler funktioniert nur, wenn Sie nur einen Server verwenden. Wenn Sie mehrere Hosts haben, dürfen Sie diesen Helfer nicht verwenden.

Sie könnten den EntityManager auch überschreiben, um eine neue Funktion wie validateAndFlush($entity) zu erstellen, die den LockHandler und den Validierungsprozess selbst verwaltet.

    
Jules Lamur 29.11.2016 13:20
quelle
0

Konnte die eindeutige Einschränkung nicht auf Datenbankebene festgelegt werden? Sie können auch die Doctrine2-Dokumentation überprüfen wie man das macht:

%Vor%

Jetzt haben Sie eine einzigartige Einschränkung auf Datenbankebene (derselbe Benutzername kann also nie zweimal in die Benutzertabelle eingefügt werden).

Wenn Sie die Einfügeoperation ausführen, erhalten Sie eine Ausnahme, falls der Benutzername bereits existiert (a UniqueConstraintViolationException ). Sie können die Ausnahme abfangen und eine gültige Antwort an den Client zurücksenden, wo Sie mitteilen, dass dieser Benutzername bereits verwendet wurde (war in Ihrer Datenbank).

    
Wilt 01.12.2016 15:24
quelle
0

Wenn ich die Frage richtig verstanden habe, haben Sie sich selbst eine hohe Grenze gesetzt. Es ist für Ihre Persistenzschicht eindeutig unmöglich, die Zukunft zu sehen. Daher ist es unmöglich, einen Validator zu unterstützen, der garantiert, dass die Einfügung erfolgreich ist (und keine UniqueConstraintViolationException auslöst), wenn nur Ihre Domain-Entitäten verwendet werden. Sie müssen irgendwo einen zusätzlichen Status beibehalten.

Wenn Sie eine schrittweise Verbesserung wünschen, benötigen Sie eine Möglichkeit, den Benutzernamen zur Validierungszeit zu reservieren. Das ist natürlich einfach - Sie erstellen einfach eine Liste, um "In-Flight" -Nutzernamen zu verfolgen und überprüfen diese Liste zusätzlich zur Überprüfung Ihrer Persistenzschicht während der Validierung.

Wo es schwierig wird, einen vernünftigen Weg zu finden, diese Liste zu beschneiden und Benutzernamen freizugeben, die zur Validierung eingereicht, aber nie bei einer erfolgreichen Registrierung verwendet werden.

Das ist ein Implementierungsdetail, und Sie müssen überlegen, wie lange eine User-Reservierung bestehen bleibt.

Eine einfache Implementierung von ganz oben: Pflegen Sie eine Tabelle in Ihrer Datenbank mit (username, session_id, reserved_at) und lassen Sie regelmäßig alle Zeilen löschen, in denen reserved_at & lt; : datetime.

Sie müssen die Sitzungs-ID verfolgen, da Sie den Nutzernamen für einen bestimmten Benutzer reservieren. Da der Benutzer noch kein Konto erstellt hat, können sie nur über die Sitzungs-ID identifiziert werden.

    
timdev 01.12.2016 19:58
quelle

Tags und Links