Laravel 5.4 - So verwenden Sie mehrere Fehlermeldungen für dieselbe benutzerdefinierte Validierungsregel

8

Um den Code wiederzuverwenden, habe ich eine eigene Validierungsregel in einer Datei namens ValidatorServiceProvider erstellt:

%Vor%

Und ich benutze diese Regel so:

%Vor%

Aber ich möchte für jeden Fall verschiedene Fehlermeldungen einstellen, etwa so:

%Vor%

Aber ich finde nicht heraus, wie ich das erreichen kann, ohne zwei verschiedene Regeln zu machen ...
Natürlich könnte es mit mehreren Regeln arbeiten, aber es wird auch mehrere SQL-Abfragen durchführen, und das möchte ich wirklich vermeiden.
Denken Sie auch daran, dass ich im realen Fall mehr als 2 Validierungen wie Thesen in einer einzigen Regel haben könnte.

Hat jemand eine Idee?

=====
EDIT 1:

Eigentlich denke ich, dass ich etwas möchte, das auf ähnliche Weise funktioniert wie die Regeln beetween oder size .
Sie stellen eine einzige Regel dar, bieten jedoch mehrere Fehlermeldungen:

%Vor%

Laravel prüft, ob der Wert eine Zahl, eine Datei, eine Zeichenfolge oder ein Array darstellt. und erhält die richtige Fehlermeldung zu verwenden.
Wie erreichen wir so etwas mit einer benutzerdefinierten Regel?

    
Marc 22.06.2017, 09:57
quelle

3 Antworten

3

Leider bietet Laravel derzeit keine Möglichkeit, Ihre Validierungsregel direkt aus Ihrem Attributparameter-Array hinzuzufügen und aufzurufen. Aber das schließt eine mögliche und freundliche Lösung basierend auf Trait und Request Nutzung nicht aus.

Hier finden Sie meine Lösung zum Beispiel.

Als Erstes müssen Sie darauf warten, dass das Formular verarbeitet wird, um die Formularanforderung mit einer abstrakten Klasse zu bearbeiten. Was Sie tun müssen, ist, die aktuelle Validator -Instanz zu erhalten und zu verhindern, dass weitere Validierungen durchgeführt werden, wenn ein relevanter Fehler vorliegt. Andernfalls speichern Sie die Validatorinstanz und rufen Ihre benutzerdefinierte Benutzervalidierungsregelfunktion auf, die Sie später erstellen:

%Vor%

Der nächste Schritt besteht darin, Ihre Trait zu erstellen, die dank der aktuellen Validator-Instanz die Möglichkeit bietet, Ihre Eingaben zu validieren und die korrekte Fehlermeldung zu verarbeiten, die Sie anzeigen möchten:

%Vor%

Vergessen Sie nicht, Ihre MyCustomFormRequest zu verlängern. Zum Beispiel nach Ihrem php artisan make:request CreateUserRequest , hier ist der einfache Weg dazu:

%Vor%

Ich hoffe, dass Sie Ihren Weg finden, was ich vorschlage.

    
Sense 30.06.2017, 09:52
quelle
5

Schlechter Umgang mit benutzerdefinierten Validierungsregeln ist der Grund, warum ich Laravel fallen gelassen habe (naja, das war einer von vielen Gründen, aber es war der Strohhalm, der sozusagen das Fass zum Überlaufen brachte). Aber trotzdem habe ich eine dreiteilige Antwort für Sie: ein Grund, warum Sie das in diesem speziellen Fall nicht machen wollen, einen schnellen Überblick über das Chaos, mit dem Sie sich befassen müssen, und dann die Antwort auf Ihre Frage Du willst es immer noch tun.

Wichtige Sicherheitsbedenken

Die besten Sicherheitsmaßnahmen für die Verwaltung von Anmeldungen schreiben vor, dass Sie immer eine allgemeine Fehlermeldung für Anmeldeprobleme zurückgeben sollten. Das entscheidende Gegenbeispiel wäre, wenn Sie "Diese E-Mail ist nicht in unserem System registriert" für eine E-Mail nicht gefunden und "Falsches Passwort" für eine korrekte E-Mail mit dem falschen Passwort. Wenn Sie separate Validierungsnachrichten geben, geben Sie potenziellen Angreifern zusätzliche Informationen darüber, wie sie ihre Angriffe effektiver steuern können. Aus diesem Grund sollten alle loginbezogenen Probleme unabhängig von der zugrunde liegenden Ursache eine generische Überprüfungsmeldung zurückgeben, was auf "ungültige E-Mail / Kennwort-Kombination" zurückzuführen ist. Dasselbe gilt für Formulare zur Passwortwiederherstellung, die oft so etwas wie "Die Anweisungen zur Passwortwiederherstellung wurden an diese E-Mail gesendet, wenn sie in unserem System vorhanden sind" enthalten. Andernfalls geben Sie Angreifern (und anderen) eine Möglichkeit zu erfahren, welche E-Mail-Adressen in Ihrem System registriert sind und welche zusätzliche Angriffsvektoren darstellen können. In diesem bestimmten Fall ist eine Validierungsnachricht das, was Sie wollen.

Das Problem mit Laravel

Das Problem, auf das Sie stoßen, ist, dass Laravel-Validierer einfach wahr oder falsch zurückgeben, um anzuzeigen, ob die Regel erfüllt ist oder nicht. Fehlermeldungen werden separat behandelt. Sie können die Validator-Fehlermeldung in Ihrer Validator-Logik nicht angeben. Ich kenne. Es ist lächerlich und schlecht geplant. Sie können nur wahr oder falsch zurückgeben. Sie haben keinen Zugriff auf etwas anderes, um Ihnen zu helfen, also wird Ihr Pseudocode es nicht tun.

Die (hässliche) Antwort

Am einfachsten erstellen Sie Ihre eigenen Validierungsnachrichten, indem Sie Ihren eigenen Validator erstellen . Das sieht ungefähr so ​​aus (in Ihrem Controller):

%Vor%

Sie müssten Ihren Validator immer noch beim Booten erstellen (Ihren Valiator::Extend -Aufruf. Dann können Sie die $rules normal angeben, indem Sie sie an Ihren benutzerdefinierten Validator übergeben. Schließlich können Sie Ihre Nachrichten angeben. insgesamt (in Ihrem Controller):

%Vor%

(Ich kann mich nicht erinnern, ob Sie jede Regel in Ihrem $messages -Array angeben müssen. Ich glaube nicht). Natürlich ist auch das nicht sehr beeindruckend, denn was Sie für $ -Nachrichten übergeben, ist einfach ein Array von Strings (und das ist alles, was es sein darf). Daher kann diese Fehlernachricht aufgrund von Benutzereingaben nicht immer leicht geändert werden. Dies alles passiert, bevor Ihr Validator auch läuft. Ihr Ziel ist es, die Validierungsnachricht abhängig von den Validierungsergebnissen zu ändern, jedoch zwingt Laravel Sie, die Nachrichten zuerst zu erstellen. Um wirklich das zu tun, was Sie tun wollen, müssen Sie den tatsächlichen Fluss des Systems anpassen, was nicht besonders toll ist.

Eine Lösung wäre eine Methode in Ihrem Controller, die berechnet, ob Ihre benutzerdefinierte Validierungsregel erfüllt ist. Es würde dies tun, bevor Sie Ihren Validator erstellen, damit Sie eine entsprechende Nachricht an den von Ihnen erstellten Validator senden können. Wenn Sie dann die Validierungsregel erstellen, können Sie sie auch an die Ergebnisse Ihres Validierungsrechners binden, solange Sie die Regeldefinition in Ihren Controller verschieben. Sie müssen nur sicherstellen, dass die Dinge nicht versehentlich geöffnet werden. Sie müssen auch bedenken, dass dies erfordert, Ihre Validierungslogik außerhalb der Validatoren zu verschieben, was ziemlich hacky ist. Leider bin ich mir zu 95% sicher, dass es wirklich keinen anderen Weg gibt, dies zu tun.

Ich habe unten einen Beispielcode. Es hat definitiv einige Nachteile: Ihre Regel ist nicht mehr global (es ist im Controller definiert), die Validierungslogik verlässt den Validator (was gegen das Prinzip des geringsten Erstaunens verstößt), und Sie müssen sich einen In einfallen lassen -Objekt-Caching-Schema (was nicht schwer ist), um sicherzustellen, dass Sie Ihre Abfrage nicht zweimal ausführen, da die Validierungslogik zweimal aufgerufen wird. Ich wiederhole, es ist definitiv hacky, aber ich bin mir ziemlich sicher, dass dies die einzige Möglichkeit ist, das zu tun, was Sie mit Laravel machen wollen. Es mag bessere Wege geben, das zu organisieren, aber das sollte dir zumindest eine Vorstellung davon geben, was du tun musst.

%Vor%

Es ist auch eine kurze Bemerkung wert, dass diese Implementierung auf $this Unterstützung für Schließungen angewiesen ist, die (wie ich glaube) in PHP 5.4 hinzugefügt wurde. Wenn Sie eine alte Version von PHP verwenden, müssen Sie% code_% für den Abschluss mit $this angeben.

Bearbeiten, um zu schimpfen

Worauf es wirklich ankommt, ist, dass das Laravel-Validierungssystem sehr granular ist. Jede Validierungsregel soll nur eine Sache validieren. Aus diesem Grund sollte die Validierungsnachricht für einen gegebenen Validator niemals geändert werden müssen. Daher akzeptiert use (wenn Sie einen eigenen Validator erstellen) nur einfache Strings.

Im Allgemeinen ist Granularität eine gute Sache im Anwendungsdesign und etwas, das die korrekte Implementierung von SOLID-Prinzipien anstrebt. Diese spezielle Implementierung macht mich jedoch verrückt. Meine allgemeine Programmierphilosophie ist, dass eine gute Implementierung die häufigsten Anwendungsfälle sehr einfach machen und dann für die weniger gebräuchlichen Anwendungsfälle aus dem Weg sein sollte. In diesen Fällen macht die Architektur von Laravel die häufigsten Anwendungsfälle einfach, die weniger gebräuchlichen Anwendungsfälle jedoch nahezu unmöglich. Mit dieser Abwägung bin ich nicht einverstanden. Mein allgemeiner Eindruck von Laravel war, dass es großartig funktioniert, solange man Dinge auf Laravel-Art machen muss, aber wenn man aus irgendeinem Grund aus der Box treten muss, wird es dein Leben aktiv erschweren. In Ihrem Fall ist die beste Antwort wahrscheinlich, einfach in diese Box zurückzugehen, d. H. Zwei Validatoren zu machen, selbst wenn dies bedeutet, eine redundante Abfrage durchzuführen. Die tatsächlichen Auswirkungen auf Ihre Anwendungsperformance werden wahrscheinlich überhaupt keine Rolle spielen, aber der Erfolg, den Sie für Ihre langfristige Wartbarkeit haben werden, damit Laravel sich so verhält, wie Sie es möchten, wird ziemlich groß.

    
Conor Mancone 29.06.2017 13:09
quelle
0

Wo haben Sie die Fehlermeldungen für die Größenprüfung gefunden?

Ich habe die Validierungsregeln in der Illuminate\Validation\ConcernsValidatesAttributes Merkmal und alle Funktionen geben einen bool Wert zurück (auch die Größenüberprüfung).

%Vor%

Was Sie gefunden haben, gehört zu diesem Teil:

%Vor%

In diesem Fall dient die Formatierung nur dazu, die Ausgabe zu formatieren, indem ein lowerRule -Wert gesetzt wird, den Laravel in speziellen Fällen behandelt, wie die Größenvalidierung:

%Vor%

So lange Validierungsregeln einen bool-Wert zurückgeben müssen, gibt es keine Möglichkeit, mehr als eine Fehlermeldung zurückzugeben. Sonst müssen Sie einige Parteien der Validierungsregeln neu schreiben.

Ein Ansatz für Ihr Problem mit der Validierung Sie könnten die Existenz-Validierung verwenden:

%Vor%

Sie müssten also 2 Validierungsregeln verwenden. Ich würde vorschlagen, das vorhandene von Laravel zu verwenden, um zu überprüfen, ob die E-Mail festgelegt ist, und eine benutzerdefinierte, um zu überprüfen, ob das Konto validiert ist.

    
mimo 26.06.2017 08:34
quelle