Laravel 5.4 - Wie man mehrere Fehlermeldungen für denselben benutzerdefinierten Gültigkeitsregel
Um die Wiederverwendung von code, habe ich meinen eigenen validator Regel in einer Datei mit dem Namen ValidatorServiceProvider :
class ValidatorServiceProvider extends ServiceProvider
{
public function boot()
{
Validator::extend('checkEmailPresenceAndValidity', function ($attribute, $value, $parameters, $validator) {
$user = User::where('email', $value)->first();
//Email has not been found
if (! $user) {
return false;
}
//Email has not been validated
if (! $user->valid_email) {
return false;
}
return true;
});
}
public function register()
{
//
}
}
Und ich verwende eine Regel wie diese :
public function rules()
{
return [
'email' => 'bail|required|checkEmailPresenceAndValidity'
];
}
Aber, ich möchte verschiedene Fehlermeldungen für jeden Fall, so etwas wie dieses :
if (! $user) {
$WHATEVER_INST->error_message = 'email not found';
return false;
}
if (! $user->valid_email) {
$WHATEVER_INST->error_message = 'invalid email';
return false;
}
Aber ich nicht herausfinden, wie dies zu erreichen, ohne dabei 2 verschiedene Regeln ...
Natürlich könnte es klappen mit mehreren Regeln, sondern es wird auch die Ausführung mehrerer SQL-Abfragen, und ich wirklich wollen, dies zu vermeiden.
Auch im Auge behalten, dass im realen Fall hätte ich mehr als 2 Validierungen wie Thesen in einer einzigen Regel.
Hat jemand eine Idee ?
=====
EDIT 1 :
Eigentlich, denke ich, dass ich will, dass etwas funktioniert in einer ähnlichen Art und Weise als die beetween
oder size
Regeln.
Sie repräsentieren eine einzige Regel, bieten aber mehrere Fehlermeldungen :
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
Laravel prüft, ob der Wert steht für eine numerische, eine Datei, einen string oder ein array sein ; und wird die richtige Fehlermeldung zu verwenden.
Wie erreichen wir diese Art der Sache mit benutzerdefinierten Regel ?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Leider Laravel nicht aktuell ein konkreter Weg, um hinzuzufügen, und rufen Sie Ihre überprüfung in der Regel direkt von Ihrem Attribut params-array. Aber das schließt nicht aus, eine mögliche und freundliche Lösung basiert auf
Trait
undRequest
Nutzung.Anbei meine Lösung für das Beispiel.
Erste Sache ist, zu warten, bis die form verarbeitet werden, zu behandeln Sie das Formular Anfrage ourselve mit einer abstrakten Klasse. Was Sie tun müssen, ist zu Holen Sie sich die aktuellen
Validator
Instanz und verhindern, dass weitere Validierungen, wenn es einen entsprechenden Fehler. Andernfalls speichern Sie die validator-Instanz und rufen Sie Ihre benutzerdefinierten Gültigkeitsregel-Funktion, die Sie später erstellen :Nächsten Schritt erstellen Sie Ihre
Trait
die den Weg, um überprüfen Sie Ihre Eingaben, Dank der aktuellen validator-Instanz und Griff den richtigen Fehler-Nachricht, die Sie anzeigen möchten :Schließlich, vergessen Sie nicht zu erweitern, Ihre
MyCustomFormRequest
. Zum Beispiel, wenn Sie Ihrephp artisan make:request CreateUserRequest
, hier ist der einfache Weg, dies zu tun :Ich hoffe, dass Sie finden Ihren Weg in das, was ich vorschlagen.
$this->v
, aber es ist nur dort, weilMyCustomFormRequest
füllt es. Das bedeutet, dass dieses Merkmal überhaupt nicht wiederverwendbar, die Niederlagen der Zweck der Merkmale. Ich glaube, Sie wäre besser dran, Notwasserung das Merkmal bewegtvalidateUserEmailAndValidity
inCreateUserRequest
oder stellen Sie den validator ein erforderlicher parameter, der in Ihrem Zug, anstatt es aus$this->v
.Schlechten Umgang mit der benutzerdefinierte Validierungsregeln ist der Grund, warum ich ditched laravel (gut, es war einer der vielen Gründe, aber es war der Tropfen, der das Kamel brach ' zurück, um so zu sprechen). Aber egal, ich habe eine dreiteilige Antwort für Sie: ein Grund, warum Sie nicht wollen, dies zu tun, in diesem konkreten Fall, einen schnellen überblick über die Sauerei, die Sie zu bewältigen haben, und dann die Antwort auf Ihre Frage in den Fall, Sie wollen immer noch, es zu tun.
Wichtig Sicherheit Sorge
Best security practices für die Verwaltung von Anmeldungen zu diktieren, sollten Sie immer eine generische Fehlermeldung für login-Probleme. Die Quintessenz der Zähler-Beispiel wäre, wenn Sie zurückgegeben ", Dass E-Mail nicht registriert ist mit unserem system" für eine E-Mail-nicht-gefunden und "Falsches Passwort" für eine korrekte E-Mail mit dem falschen Passwort. In dem Fall, wo Sie geben separate Validierung der Nachrichten, die Sie geben potentiellen Angreifer zusätzliche Informationen darüber, wie Sie effektiver, richten Ihre Angriffe. Als Ergebnis werden alle login-Problemen zurückkehren sollte, eine generische Validierung Nachricht, unabhängig von der zugrunde liegende Ursache, die etwas zum Effekt von "Invalid E-Mail/Passwort Kombination". Das gleiche gilt für die Passwort-Wiederherstellung Formen, die oft etwas sagen wie, "Passwort-Wiederherstellung Anweisungen erhalten haben, dass E-Mail, wenn Sie vorhanden ist in unserem system". Ansonsten geben Sie Angreifern (und andere) eine Möglichkeit zu wissen, was E-Mail-Adressen registriert sind, mit Ihrem system, und können, setzen zusätzliche Angriffsvektoren. Also in diesem insbesondere Fall einer Validierung der Nachricht ist, was Sie wollen.
Die Mühe mit laravel
Das Problem, das Sie laufen in ist, dass laravel Prüfungen einfach true oder false zurück, um zu Kennzeichnen, ob oder nicht die Regel ist erfüllt. Fehlermeldungen werden separat behandelt. Sie insbesondere angeben können, der validator die Fehlermeldung aus der eigenen validator Logik. Ich weiß. Es ist lächerlich und schlecht geplant. Alles, was Sie tun können, ist true oder false zurück. Sie haben keinen Zugriff auf irgendetwas anderes, Ihnen zu helfen, damit Ihre pseudo-code der nicht gehen, es zu tun.
Die (unschöne) Antwort
Der einfachste Weg, um erstellen Sie Ihr eigenes Validierung von Nachrichten ist erstellen Sie Ihre eigenen validator. Das sieht ungefähr so aus (im inneren des Controllers):
Müssten Sie noch schaffen die eigene Prüfung auf boot (Ihr
Valiator::Extend
nennen. Dann können Sie die$rules
normalerweise, indem man Sie in Ihrer benutzerdefinierten validator. Schließlich können Sie angeben, Ihre Nachrichten. So etwas wie dieses, insgesamt (im inneren des Controllers):(Ich erinnere mich nicht, wenn Sie angeben müssen, die jede Regel in Ihrem
$messages
array. Ich glaube nicht, dass es so ist). Natürlich, auch das ist nicht sehr genial, was du da pass für $messages ist einfach ein array von strings (und das ist alles was es sein darf). Als Ergebnis, werden Sie noch nicht haben, können diese Fehlermeldung leicht ändern, je nach Benutzereingabe. Dies alles geschieht vor Ihren validator läuft auch. Ihr Ziel ist es, die Validierung der Nachricht ändern sich je nach den Ergebnissen der Validierung, aber laravel Kräfte, die Sie zum erstellen der Nachrichten zunächst. Als ein Ergebnis, um wirklich zu tun, was Sie tun möchten, Sie müssen, um die tatsächliche Strömung des Systems, das ist nicht sehr genial.Eine Lösung wäre es, eine Methode im controller, der berechnet, ob oder nicht Ihre benutzerdefinierte Gültigkeitsregel erfüllt ist. Es würde dies tun, bevor Sie Ihre Bestätigung, so dass Sie können senden Sie eine entsprechende Nachricht an den validator, die Sie bauen. Dann, wenn Sie erstellen die Validierung Regel, können Sie auch binden Sie es auf die Ergebnisse Ihrer Validierungs-Rechner, so lange wie Sie sich bewegen, Ihre Regel-definition im inneren des Controllers. Sie müssen nur sicherstellen, dass und nicht zufällig nennen die Dinge nicht in Ordnung. Sie haben auch zu beachten, dass dies erfordert, bewegen Sie Ihre Validierungslogik außerhalb der Prüfungen, die ziemlich hacky. Leider, ich bin 95% sicher, dass es wirklich keinen anderen Weg, dies zu tun.
Habe ich einige Beispiel-code unten. Es hat auf jeden Fall einige draw-Rücken: die Regel ist nicht mehr global (ist definiert in der Steuerung), die Validierungs-Logik bewegt sich der validator (das verstößt gegen das Prinzip der geringsten Verwunderung), und Sie haben zu kommen mit einer in-Objekt-caching-System (das ist nicht schwer), um sicherzustellen, dass Sie nicht führen Sie Ihre Abfrage zweimal, da die Validierung Logik ist zweimal genannt. Zu wiederholen, es ist definitiv hacky, aber ich bin mir ziemlich sicher, dass dies der einzige Weg, das zu tun, was Sie tun möchten, mit laravel. Möglicherweise gibt es bessere Wege das zu organisieren, aber dies sollte zumindest geben Ihnen eine Idee von, was Sie brauchen, um passieren.
Ist es auch, lohnt sich ein kurzer Hinweis, dass diese Implementierung setzt auf
$this
Unterstützung für closures, die (glaube ich) wurde Hinzugefügt in PHP 5.4. Wenn Sie auf einer alten version von PHP du wirst$this
den Verschluss mituse
.Bearbeiten zu schimpfen
Was es wirklich hinausläuft, ist, dass die laravel validation system wurde entwickelt, um sehr fein abgestimmt werden. Jede Validierungsregel wird speziell eigentlich nur bestätigen, was. Als Ergebnis der Validierung Nachricht für eine angegebene Prüfung sollte nie geändert werden müssen, also warum
$messages
(wenn Sie bauen Sie Ihre eigenen validator) akzeptiert nur die plain-strings.Im Allgemeinen Granularität ist eine gute Sache, application design, und etwas, dass die ordnungsgemäße Durchführung von FESTEN Prinzipien Streben. Jedoch, diese Art der Implementierung macht mich verrückt. Meine Allgemeine Programmier-Philosophie ist, dass eine gute Umsetzung sollten die häufigsten nutzt-Fällen sehr einfach, und dann raus aus dem Weg, für die weniger häufige Anwendungsfälle. In diesen Fällen ist die Architektur von laravel die häufigsten Anwendungsfälle einfach, aber die weniger häufige Anwendungsfälle fast unmöglich. Ich bin nicht in Ordnung mit, dass der Handel aus. Mein allgemeiner Eindruck von Laravel war, dass es wunderbar funktioniert, so lange, wie Sie benötigen, Dinge zu tun, die laravel Weg, aber wenn Sie haben, um Schritt aus der box aus irgendeinem Grund, es geht um aktiv Ihr Leben erschweren. In Ihrem Fall die beste Antwort ist wahrscheinlich nur Schritt rechts zurück in die box, d.h. zwei Prüfern, auch wenn es bedeutet, dass eine redundante Abfrage. Die tatsächlichen Auswirkungen auf die Leistung Ihrer Anwendung wird wahrscheinlich nicht egal, aber die Treffer werden Sie ergreifen, um Ihre langfristige Wartbarkeit zu bekommen laravel zu Verhalten, wie Sie wollen, es wird ziemlich groß sein.
Alternativ zu den anderen Vorschlägen, ich denke, Sie können auch telefonisch
Validator::replacer('yourRule', function())
nebenValidator::extend('yourRule', function(...))
und verfolgen, was bewirkt, dass die Validierung Fehler in den service-provider-Klasse vergrößern Sie den validator aus. Auf diese Weise sind Sie in der Lage sein, um vollständig ersetzen Sie die Standard-Fehler-Meldung mit einer anderen.Laut docs,
replacer()
gemeint ist, für die Herstellung von Platzhalter-Ersetzungen in der Fehlermeldung, bevor es zurückgegeben wird, so ist dies zwar nicht streng, der Fall, ist es nahe genug. Natürlich, es ist eine Art hässlich(ish) umgehen, aber es wird wahrscheinlich funktionieren (zumindest scheint es für mich arbeiten, auf den ersten Blick).Einer Sache, zum im Verstand zu halten ist aber, dass Sie wahrscheinlich zu verfolgen, diese Fehler in einem array, wenn Sie vermeiden wollen automatisch Rücksendung gleiche Nachricht für alle Felder, die konnte Ihre benutzerdefinierte Gültigkeitsregel.
Wo haben Sie den Fehler gefunden-Nachrichten für die Größe Validierung?
Ich schaute auf die Validierungsregeln in der
Illuminate\Validation\ConcernsValidatesAttributes
Merkmal und alle Funktionen geben einen booleschen Wert (auch von der Größe Validierung).Was Sie gefunden haben, gehört zu diesem Teil:
In diesem Fall ist es nur für die Formatierung der Ausgabe, indem ein
lowerRule
Wert, dass laravel Griffe in besonderen Fällen, wie die Größe Validierung:So lange, wie Validierungsregeln sind zur Rückgabe ein boolescher Wert, es gibt keine Möglichkeit zur Rückkehr mehr als eine Fehlermeldung. Ansonsten müssen Sie neu schreiben einige Partei der Validierungs-Regeln.
Einen Ansatz für dein problem mit der Validierung konnte man mit dem exists-Validierung:
So müssten Sie 2 existiert Validierungs-Regeln. Ich würde empfehlen, das bestehende von laravel zu überprüfen, ob die E-Mail festgelegt ist, und einer eigenen, um zu überprüfen, ob das Konto überprüft wird.