Zum Hauptinhalt springen
Um aus einem verteilten Paket eine String-Regel wie 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 vorgestellten ValidationRule-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 wie AC-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 in src/Validation/TrackingCode.php einen Handler für die String-Regel an. Diese Klasse implementiert das Interface ValidationRule nicht.
Der Callback erhält vier Argumente: den Attributnamen, den Eingabewert, das Parameter-Array und den gerade validierenden Validator. Bei 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 in boot() 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.
Wenn ein Replacer die gesamte Meldung stets durch einen festen Text ersetzt, ignoriert er die Überschreibungen der Nutzer in messages() und in Übersetzungen. Das obige Beispiel ersetzt nur :prefix in der übergebenen $message.
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.
Zur Vorbereitung von Übersetzungsdateien und zur Locale-Konfiguration siehe Lokalisierung. Wenn Sie bei der Registrierung __('...') 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 in boot() 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.
Legen Sie in der 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, steht extendDependent() 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.
Die Registrierung als Dependent garantiert weder die Existenz des referenzierten Felds noch dessen bereits validierten Zustand. 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 Datei tests/Feature/TrackingRuleTest.php. Zusätzlich zu Unit-Tests der Klasse prüfen Sie hier Registrierung und Meldungsverarbeitung über die tatsächliche Factory.
Der letzte Test verändert die gemeinsam genutzte Factory nicht, sondern erstellt eine neue Factory und prüft das Kopieren der registrierten Inhalte. Wenn Sie auch die Beispiele mit Namespace-Übersetzungen oder Dependent-Regeln bereitstellen, ergänzen Sie zusätzliche Tests in einer Umgebung, die die entsprechenden Registrierungen enthält.

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 null sowie Kombinationen mit nullable, sometimes und bail prü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.
Zur Testumgebung für ein Paket allein siehe Pakete testen, zum Umgang mit Kompatibilität siehe auch Versionskompatibilität von Paketen verwalten.

Herangezogene Primärquellen

Zuletzt geändert am 5. November 2026