acme_tracking:AC bereitzustellen, registrieren Sie die Prüflogik in der Factory der Validierung. In den Form Requests der nutzenden Anwendung lässt sie sich dann mit derselben Schreibweise wie die eingebauten Regeln verwenden.
Diese Seite basiert auf der offiziellen Implementierung von Laravel Framework v13.40.0. Sie ergänzt die Grundbeispiele aus Benutzerdefinierte Validierungsregeln und behandelt Registrierung, Übersetzung und die Lebensdauer des Zustands, wenn Sie die Regel als öffentliche API eines Pakets pflegen.
Abgrenzung zu Regelobjekten
Die in der offiziellen Dokumentation vorgestelltenValidationRule-Objekte können auch in Paketen verwendet werden. Sofern die Angabe als String nicht selbst eine Anforderung ist, sollten Sie ein Objekt in Betracht ziehen, das typisierte Argumente über den Konstruktor entgegennimmt.
Trotz des gleichen Namens
validate() unterscheiden sich die Aufrufverträge. Wenn Sie eine Klasse, die ValidationRule implementiert, unverändert als Klassen-String an Factory::extend() übergeben, passen weder der Typ des dritten Arguments noch der Rückgabewert.
Registrierung, Erzeugung und Validierung trennen
extend() der Validator-Fassade ist ein Aufruf an Illuminate\Validation\Factory. Dies ist ein anderes Objekt als die Illuminate\Validation\Validator-Instanz, die die Eingaben prüft.
Das Diagramm zeigt den Ablauf, wenn eine String-Regel ausgeführt wird. Das Überspringen bei fehlender Eingabe oder durch nullable wird weiter unten behandelt.
Die Factory wird als Singleton unter dem Schlüssel validator registriert, doch der von make() der Standardimplementierung zurückgegebene Validator wird jedes Mal neu erzeugt. Nachträgliche Registrierungen in der Factory aktualisieren nicht das Erweiterungs-Array bereits erzeugter Validatoren.
Paketspezifische Regeln registrieren
Als Beispiel validieren wir einen fiktiven Sendungscode aus einem Präfix in ASCII-Großbuchstaben, einem Bindestrich und acht Ziffern. Ein Format wieAC-00000001 dient nur als Beispiel und entspricht nicht der Nummernspezifikation eines realen Versanddienstleisters.
Angenommen wird ein Aufbau, bei dem der Paket-Namespace Acme\Courier\ per Composer PSR-4 auf src/ abgebildet wird und ein regulärer, nicht verzögerter Service Provider geladen wird. Zum Laden des Providers siehe Automatische Paketerkennung.
Die Prüflogik in eine Klasse auslagern
Legen Sie insrc/Validation/TrackingCode.php einen Handler für die String-Regel an. Diese Klasse implementiert das Interface ValidationRule nicht.
acme_tracking:AC lautet das Parameter-Array ['AC']. Auch die Regel selbst prüft den Typ des Werts, damit sie bei alleiniger Verwendung keinen Typfehler auslöst.
Ein ungültiges Präfix oder eine falsche Parameteranzahl wird nicht als Eingabefehler des Benutzers, sondern als Konfigurationsfehler in der Regeldefinition mit einer Exception behandelt. Wird die Regel bei leeren Werten übersprungen, läuft auch diese Konfigurationsprüfung nicht. Daher brauchen Sie zusätzlich Tests mit gültigen, nicht leeren Werten.
Nach der Auflösung der Factory registrieren
Registrieren Sie die Regel und die Meldungsersetzung inboot() von src/CourierServiceProvider.php.
callAfterResolving() wartet auf die Erzeugung, falls die Factory noch nicht aufgelöst ist, und registriert bei einer bereits aufgelösten Factory sofort. Details zum Hook selbst finden Sie unter Hooks nach der Service-Auflösung in Paketen.
Der Klassen-String TrackingCode::class.'@validate' löst die Klasse zur Validierungszeit über den Container auf und ruft die Methode auf. Auch ohne @validate, also nur mit dem Klassennamen, ist der Standard-Methodenname validate. Hat die Klasse Konstruktorabhängigkeiten, binden Sie diese so, dass der Container sie auflösen kann.
Dieses Beispiel registriert den Handler weder als Singleton noch besitzt es Eigenschaften, die Eingaben speichern. Daten zur Validierungszeit werden über die Argumente verarbeitet, und die von der Factory gehaltenen Closures sollten keinen anfragespezifischen Zustand einfangen.
In der nutzenden Anwendung angeben
bail bricht die nachfolgenden Regeln ab, sobald eine vorhergehende Regel dieses Attributs fehlschlägt. Die Rollen werden getrennt: required für die Pflichtangabe, acme_tracking für das Format.
Verwenden Sie für öffentliche Namen einheitlich eindeutiges snake_case wie acme_tracking. Wird derselbe Name für dieselbe Art von Erweiterung erneut registriert, überschreibt die spätere Registrierung die frühere. Existiert außerdem eine eingebaute Methode wie validateRequired(), wird diese direkt aufgerufen, sodass sich eine eingebaute Prüfung nicht durch eine gleichnamige Erweiterung ersetzen lässt.
Fehlermeldungen der Nutzer erhalten
Die Meldung einer normalen String-Regel wird ungefähr in der folgenden Rangfolge ausgewählt. Sonderfälle wie Größenregeln werden hier nicht behandelt.
Nachdem Laravel
:attribute usw. ersetzt hat, wird der benutzerdefinierte Replacer aufgerufen. Der Replacer erhält fünf Argumente: die ausgewählte Meldung, den Attributnamen, den Regelnamen, das Parameter-Array und den Validator. Im obigen Beispiel wird das nicht verwendete fünfte Argument weggelassen.
Um in der Anwendung einen japanischen Standardtext festzulegen, fügen Sie dem zurückgegebenen Array der bestehenden lang/ja/validation.php den Eintrag acme_tracking hinzu. Das folgende Beispiel zeigt nur den hinzuzufügenden Eintrag und entfernt keine anderen eingebauten Meldungen.
__('...') ausführen und das Ergebnis als Fallback speichern, verbleibt der String in der zu diesem Zeitpunkt aktiven Locale in der Factory. In Anwendungen, die die Locale wechseln, verwenden Sie die Übersetzung zum Zeitpunkt der Fehlererzeugung.
Namespace-Übersetzungen des Pakets verwenden
Wenn Sie inboot() loadTranslationsFrom(__DIR__.'/../lang', 'acme-courier') aufrufen, können Sie z. B. auf lang/ja/validation.php des Pakets über acme-courier::validation.tracking_code zugreifen.
Allein die Übergabe eines Übersetzungsschlüssels als drittes Argument von extend() führt jedoch nicht zu einer automatischen Übersetzung. Die Factory speichert ihn lediglich als Fallback-String. Ersetzen Sie extend() und replacer() im obigen Hook durch die folgende Registrierung, wird die Übersetzung des Pakets nur dann abgerufen, wenn der Fallback ausgewählt wurde.
validation.php jeder Locale des Pakets einen Eintrag tracking_code an. Für den japanischen Text können Sie denselben Wortlaut wie beim obigen Eintrag acme_tracking verwenden.
Da hier im Replacer ein neuer Übersetzungsstring abgerufen wird, wird auch :attribute explizit an die Übersetzung übergeben. Laravels Standardersetzung wird auf diesen Rückgabewert nicht erneut angewendet. Wurde eine eigene Meldung des Nutzers ausgewählt, bleibt deren Wortlaut erhalten. Zum Überschreiben mitgelieferter Übersetzungen siehe Paketübersetzungen überschreiben und aktualisieren.
Ausführungsbedingungen von Implicit und nullable verstehen
extendImplicit() registriert eine Regel, die auch bei fehlenden Attributen oder leeren Strings als Kandidat für die Validierung gilt. Das bedeutet weder „immer fehlschlagen lassen“ noch „alle anderen Überspringbedingungen ignorieren“.
Die Tabelle vergleicht die Ausführungsbedingungen der einzelnen Regeln. Fälle, in denen die Verarbeitung vorher durch
bail, den Ausschluss von Attributen, stopOnFirstFailure() usw. abbricht, sind gesondert zu betrachten. Bei HTTP-Eingaben können leere Strings durch Middleware in null umgewandelt werden, testen Sie leere Strings und null daher getrennt.
Für die hier gezeigte Formatregel genügt die Kombination aus normalem extend() und required. Wird eine bereits veröffentlichte Regel auf Implicit umgestellt, können Eingaben fehlschlagen, die vorher nicht geprüft wurden. Behandeln Sie dies daher als Kompatibilitätsänderung.
Referenzen in Arrays mit Dependent-Regeln auflösen
Für Regeln, die den Namen eines anderen Felds als Parameter erhalten, stehtextendDependent() zur Verfügung. Bei der Validierung von items.*.confirmed_tracking wird der Parameter items.*.tracking in das Feld derselben Zeile umgewandelt, etwa items.0.tracking. Mit normalem extend() findet diese Ersetzung nicht statt.
Das Folgende ist eine Übereinstimmungsregel, um diesen Mechanismus zu veranschaulichen. Für eine einfache Gleichheitsprüfung können Sie in echten Anwendungen die eingebaute Regel same verwenden. Verstehen Sie es als Beispiel für die Anwendung auf paketspezifische feldübergreifende Prüfungen.
Fügen Sie dies der Factory hinzu, die Sie im Hook erhalten.
getData() des vierten Arguments liefert die zu validierenden Daten, nicht nur die bereits validierten. Definieren Sie die nötigen Regeln sowohl für das referenzierende als auch für das referenzierte Feld.
Außerdem wird eine Regel durch Dependent nicht zu Implicit. Die Pflichtangabe bei fehlenden oder leeren Werten muss separat angegeben werden. Da die Implementierung Punkte in den Parametern maskiert und * ersetzt, sollten Sie APIs vermeiden, die beliebige Strings außer Feldnamen in die Parameter mischen.
Von der Registrierung bis zur Validierung in der Anwendung testen
Erstellen Sie in einer Laravel-13-Anwendung, in der das Paket und der Service Provider geladen werden, die Dateitests/Feature/TrackingRuleTest.php. Zusätzlich zu Unit-Tests der Klasse prüfen Sie hier Registrierung und Meldungsverarbeitung über die tatsächliche Factory.
Prüfpunkte für die langfristige Wartung
- Regelname, Bedeutung und Anzahl der Parameter, Pflichtangabe und akzeptierte Werttypen als öffentliche API dokumentieren.
- Ungültige Parameter, fehlende Werte, leere Strings und
nullsowie Kombinationen mitnullable,sometimesundbailprüfen. messages()der Nutzer, Anzeigenamen von Attributen, Locale-Wechsel und das Überschreiben von Paketübersetzungen prüfen.- Bei Dependent-Regeln mit mehreren Zeilen und verschachtelten Arrays sicherstellen, dass keine Werte anderer Zeilen referenziert werden.
- Die Registrierung sowohl bei noch nicht aufgelöster als auch bei bereits aufgelöster Factory prüfen und nicht erwarten, dass sie rückwirkend auf bereits erzeugte Validatoren angewendet wird.
- Namenskonflikte mit anderen Paketen vermeiden und denselben Namen nicht gemischt für normale, Implicit- und Dependent-Registrierungen verwenden.
- Beim Ausrollen von Änderungen auf langlebige Worker die Prozesse neu starten und keine Eingaben oder Benutzerinformationen in gemeinsam genutzten Handlern zurücklassen.
Herangezogene Primärquellen
- Offizielle Laravel-Dokumentation: Benutzerdefinierte Regeln und Implicit-Regeln
- Offizielle Laravel-Dokumentation: Service Provider und Übersetzungen von Paketen
- Factory: make, extend, extendImplicit, extendDependent, replacer
- Validator: Ausführungsbedingungen, Registrierung von Erweiterungen, Auflösung von Klassen
- ValidationRuleParser: Parsen von String-Regeln
- FormatsMessages: Rangfolge und Ersetzung von Meldungen
- ValidationServiceProvider: Singleton-Registrierung von validator
- ServiceProvider: callAfterResolving
- Offizielle Tests: Weitergabe von Erweiterungen und Fallbacks aus der Factory
- Offizielle Tests: String-, Klassen-, Implicit- und Dependent-Regeln