Files
michaelschiemer/docs/guides/validation.md
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

17 KiB

Validierungs-Anleitung

Diese Anleitung erklärt, wie das Validierungssystem des Frameworks funktioniert und wie Sie es effektiv nutzen können.

Grundlagen der Validierung

Die Validierung ist ein wichtiger Teil jeder Webanwendung, da sie sicherstellt, dass die Daten, die von Benutzern eingegeben werden, den erwarteten Regeln entsprechen. Das Framework bietet ein leistungsstarkes und flexibles Validierungssystem, das einfach zu verwenden ist.

Validierung in Controllern

Die einfachste Möglichkeit, Daten zu validieren, ist die Verwendung der validate-Methode in Controllern:

public function store(Request $request): Response
{
    $this->validate($request, [
        'name' => 'required|string|max:255',
        'email' => 'required|email|unique:users,email',
        'password' => 'required|string|min:8|confirmed',
        'age' => 'integer|min:18',
    ]);
    
    // Die Validierung wurde bestanden, fahren Sie mit der Speicherung fort
    $user = User::create($request->only(['name', 'email', 'password']));
    
    return $this->redirect('/users')->with('success', 'Benutzer erstellt');
}

Wenn die Validierung fehlschlägt, wird automatisch eine Antwort mit den Validierungsfehlern zurückgegeben:

  • Bei einer regulären Anfrage wird der Benutzer zur vorherigen Seite umgeleitet, und die Validierungsfehler werden in der Session gespeichert.
  • Bei einer AJAX-Anfrage wird eine JSON-Antwort mit den Validierungsfehlern und dem HTTP-Statuscode 422 zurückgegeben.

Manuelle Validierung

Sie können auch den Validator direkt verwenden, um mehr Kontrolle über den Validierungsprozess zu haben:

use App\Framework\Validation\Validator;

public function store(Request $request): Response
{
    $validator = new Validator($request->all(), [
        'name' => 'required|string|max:255',
        'email' => 'required|email|unique:users,email',
        'password' => 'required|string|min:8|confirmed',
    ]);
    
    if ($validator->fails()) {
        $errors = $validator->errors();
        
        // Fehler behandeln
        return $this->back()->withErrors($errors);
    }
    
    // Die Validierung wurde bestanden, fahren Sie mit der Speicherung fort
    $user = User::create($request->only(['name', 'email', 'password']));
    
    return $this->redirect('/users')->with('success', 'Benutzer erstellt');
}

Validierungsregeln

Das Framework bietet eine Vielzahl von Validierungsregeln, die Sie verwenden können, um Ihre Daten zu validieren.

Grundlegende Regeln

  • required: Das Feld muss vorhanden sein und darf nicht leer sein.
  • string: Das Feld muss ein String sein.
  • integer: Das Feld muss eine Ganzzahl sein.
  • numeric: Das Feld muss eine Zahl sein (Ganzzahl oder Dezimalzahl).
  • boolean: Das Feld muss ein Boolean sein (true, false, 1, 0, "1", "0").
  • array: Das Feld muss ein Array sein.
  • date: Das Feld muss ein gültiges Datum sein.
  • email: Das Feld muss eine gültige E-Mail-Adresse sein.
  • url: Das Feld muss eine gültige URL sein.
  • ip: Das Feld muss eine gültige IP-Adresse sein.
  • json: Das Feld muss ein gültiger JSON-String sein.
  • alpha: Das Feld darf nur Buchstaben enthalten.
  • alpha_num: Das Feld darf nur Buchstaben und Zahlen enthalten.
  • alpha_dash: Das Feld darf nur Buchstaben, Zahlen, Bindestriche und Unterstriche enthalten.

Größenregeln

  • min:value: Das Feld muss mindestens value groß sein.
    • Für Strings: Die Anzahl der Zeichen.
    • Für Zahlen: Der Mindestwert.
    • Für Arrays: Die Mindestanzahl der Elemente.
    • Für Dateien: Die Mindestgröße in Kilobyte.
  • max:value: Das Feld darf höchstens value groß sein.
  • size:value: Das Feld muss genau value groß sein.
  • between:min,max: Das Feld muss zwischen min und max liegen.

Vergleichsregeln

  • same:field: Das Feld muss den gleichen Wert wie field haben.
  • different:field: Das Feld muss einen anderen Wert als field haben.
  • gt:field: Das Feld muss größer als field sein.
  • gte:field: Das Feld muss größer oder gleich field sein.
  • lt:field: Das Feld muss kleiner als field sein.
  • lte:field: Das Feld muss kleiner oder gleich field sein.

Datenbankregeln

  • unique:table,column,except,idColumn: Das Feld muss in der angegebenen Tabelle und Spalte einzigartig sein.
    • table: Der Name der Tabelle.
    • column: Der Name der Spalte (standardmäßig der Feldname).
    • except: Die ID des Datensatzes, der bei der Überprüfung ignoriert werden soll (optional).
    • idColumn: Der Name der ID-Spalte (standardmäßig id).
  • exists:table,column: Das Feld muss in der angegebenen Tabelle und Spalte existieren.

Dateiregeln

  • file: Das Feld muss eine erfolgreich hochgeladene Datei sein.
  • image: Das Feld muss ein Bild sein (jpeg, png, bmp, gif, svg).
  • mimes:jpeg,png,...: Das Feld muss eine Datei mit einem der angegebenen MIME-Typen sein.
  • mimetypes:text/plain,...: Das Feld muss eine Datei mit einem der angegebenen MIME-Typen sein.
  • dimensions:min_width=100,max_width=1000,min_height=100,max_height=1000,width=100,height=100,ratio=1/1: Das Feld muss ein Bild sein, das den angegebenen Dimensionen entspricht.

Bedingte Regeln

  • required_if:anotherfield,value,...: Das Feld ist erforderlich, wenn anotherfield einen der angegebenen Werte hat.
  • required_unless:anotherfield,value,...: Das Feld ist erforderlich, es sei denn, anotherfield hat einen der angegebenen Werte.
  • required_with:foo,bar,...: Das Feld ist erforderlich, wenn eines der anderen angegebenen Felder vorhanden ist.
  • required_with_all:foo,bar,...: Das Feld ist erforderlich, wenn alle anderen angegebenen Felder vorhanden sind.
  • required_without:foo,bar,...: Das Feld ist erforderlich, wenn eines der anderen angegebenen Felder nicht vorhanden ist.
  • required_without_all:foo,bar,...: Das Feld ist erforderlich, wenn alle anderen angegebenen Felder nicht vorhanden sind.

Formatregeln

  • date_format:format: Das Feld muss dem angegebenen Datumsformat entsprechen.
  • regex:pattern: Das Feld muss dem angegebenen regulären Ausdruck entsprechen.
  • not_regex:pattern: Das Feld darf nicht dem angegebenen regulären Ausdruck entsprechen.

Bestätigungsregeln

  • confirmed: Das Feld muss ein Bestätigungsfeld haben (z.B. password_confirmation für das Feld password).
  • accepted: Das Feld muss akzeptiert werden (yes, on, 1, true).

Spezielle Regeln

  • nullable: Das Feld darf null sein.
  • present: Das Feld muss im Eingabedaten vorhanden sein, kann aber leer sein.
  • sometimes: Die Regel wird nur angewendet, wenn das Feld vorhanden ist.

Benutzerdefinierte Validierungsnachrichten

Sie können benutzerdefinierte Validierungsnachrichten angeben, um die Standardnachrichten zu überschreiben:

$this->validate($request, [
    'name' => 'required|string|max:255',
    'email' => 'required|email|unique:users,email',
    'password' => 'required|string|min:8|confirmed',
], [
    'name.required' => 'Der Name ist erforderlich',
    'email.unique' => 'Diese E-Mail-Adresse wird bereits verwendet',
    'password.min' => 'Das Passwort muss mindestens 8 Zeichen lang sein',
]);

Sie können auch Platzhalter in Ihren Nachrichten verwenden:

  • :attribute: Der Name des Feldes.
  • :min: Der Mindestwert.
  • :max: Der Maximalwert.
  • :size: Die erforderliche Größe.
  • :values: Die gültigen Werte.
  • :other: Der Name des anderen Feldes.
'min' => 'Das Feld :attribute muss mindestens :min Zeichen enthalten',

Validierung von Arrays

Sie können auch verschachtelte Arrays validieren:

$this->validate($request, [
    'user.name' => 'required|string|max:255',
    'user.email' => 'required|email|unique:users,email',
    'addresses.*.street' => 'required|string|max:255',
    'addresses.*.city' => 'required|string|max:255',
    'addresses.*.country' => 'required|string|max:255',
]);

In diesem Beispiel wird erwartet, dass user ein Array mit den Schlüsseln name und email ist, und addresses ein Array von Arrays ist, wobei jedes innere Array die Schlüssel street, city und country hat.

Benutzerdefinierte Validierungsregeln

Erstellen einer benutzerdefinierten Regel

Sie können benutzerdefinierte Validierungsregeln erstellen, indem Sie die Rule-Schnittstelle implementieren:

use App\Framework\Validation\Rule;

class StrongPassword implements Rule
{
    public function passes($attribute, $value): bool
    {
        // Überprüfen, ob das Passwort stark ist
        return preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/', $value) === 1;
    }
    
    public function message(): string
    {
        return 'Das Passwort muss mindestens 8 Zeichen lang sein und mindestens einen Großbuchstaben, einen Kleinbuchstaben, eine Zahl und ein Sonderzeichen enthalten.';
    }
}

Verwenden einer benutzerdefinierten Regel

Sie können Ihre benutzerdefinierte Regel wie folgt verwenden:

use App\Framework\Validation\Validator;

$validator = new Validator($request->all(), [
    'password' => ['required', 'string', new StrongPassword()],
]);

Oder in einem Controller:

$this->validate($request, [
    'password' => ['required', 'string', new StrongPassword()],
]);

Validierung mit Form Requests

Für komplexe Validierungslogik können Sie Form Request-Klassen erstellen:

use App\Framework\Http\FormRequest;

class CreateUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|string|min:8|confirmed',
        ];
    }
    
    public function messages(): array
    {
        return [
            'name.required' => 'Der Name ist erforderlich',
            'email.unique' => 'Diese E-Mail-Adresse wird bereits verwendet',
            'password.min' => 'Das Passwort muss mindestens 8 Zeichen lang sein',
        ];
    }
    
    public function authorize(): bool
    {
        return $this->user()->hasPermission('create-users');
    }
}

Dann können Sie die Form Request-Klasse in Ihrem Controller verwenden:

public function store(CreateUserRequest $request): Response
{
    // Die Validierung wurde bereits durchgeführt
    
    $user = User::create($request->validated());
    
    return $this->redirect('/users')->with('success', 'Benutzer erstellt');
}

Die validated-Methode gibt nur die validierten Felder zurück, was nützlich ist, um Massenänderungen zu verhindern.

Validierung von Dateien

Das Framework bietet spezielle Regeln für die Validierung von Dateien:

$this->validate($request, [
    'avatar' => 'required|file|image|max:2048', // max in Kilobyte
    'document' => 'required|file|mimes:pdf,doc,docx|max:10240',
]);

Validierung von Daten außerhalb von Requests

Sie können den Validator auch verwenden, um Daten zu validieren, die nicht aus einer HTTP-Anfrage stammen:

use App\Framework\Validation\Validator;

$data = [
    'name' => 'John Doe',
    'email' => 'john@example.com',
];

$validator = new Validator($data, [
    'name' => 'required|string|max:255',
    'email' => 'required|email',
]);

if ($validator->fails()) {
    $errors = $validator->errors();
    // Fehler behandeln
} else {
    $validatedData = $validator->validated();
    // Mit validierten Daten fortfahren
}

Validierung in JavaScript

Das Framework bietet auch eine Möglichkeit, Validierungsregeln in JavaScript zu verwenden, um clientseitige Validierung zu ermöglichen:

// In Ihrer View
<script>
    const rules = <?= json_encode($validator->jsRules()) ?>;
    const messages = <?= json_encode($validator->jsMessages()) ?>;
    
    // Verwenden Sie die Regeln mit Ihrer bevorzugten JavaScript-Validierungsbibliothek
</script>

Validierung von Abhängigkeiten

Manchmal hängt die Validierung eines Feldes vom Wert eines anderen Feldes ab. Sie können benutzerdefinierte Regeln verwenden, um diese Art von Validierung zu implementieren:

$this->validate($request, [
    'payment_type' => 'required|in:credit_card,paypal',
    'card_number' => 'required_if:payment_type,credit_card|string|size:16',
    'card_expiry' => 'required_if:payment_type,credit_card|date_format:m/y',
    'card_cvv' => 'required_if:payment_type,credit_card|string|size:3',
    'paypal_email' => 'required_if:payment_type,paypal|email',
]);

Validierung mit Bedingungen

Sie können auch komplexere Bedingungen für die Validierung definieren:

$validator = new Validator($request->all(), [
    'name' => 'required|string|max:255',
    'email' => 'required|email',
]);

$validator->sometimes('phone', 'required|string|size:10', function ($input) {
    return $input->contact_method === 'phone';
});

$validator->sometimes('address', 'required|string|max:255', function ($input) {
    return $input->requires_shipping === true;
});

Validierung von Datenbanken

Das Framework bietet Regeln für die Validierung von Datenbanken:

$this->validate($request, [
    'email' => 'required|email|unique:users,email',
    'username' => 'required|string|unique:users,username',
    'category_id' => 'required|integer|exists:categories,id',
]);

Bei der Aktualisierung eines Datensatzes möchten Sie möglicherweise den aktuellen Datensatz von der Einzigartigkeit ausschließen:

$this->validate($request, [
    'email' => 'required|email|unique:users,email,' . $userId,
    'username' => 'required|string|unique:users,username,' . $userId,
]);

Fehlerbehandlung

Zugriff auf Validierungsfehler

Wenn die Validierung fehlschlägt, können Sie auf die Fehler zugreifen:

$validator = new Validator($request->all(), [
    'name' => 'required|string|max:255',
    'email' => 'required|email|unique:users,email',
]);

if ($validator->fails()) {
    $errors = $validator->errors();
    
    // Alle Fehler abrufen
    $allErrors = $errors->all();
    
    // Fehler für ein bestimmtes Feld abrufen
    $nameErrors = $errors->get('name');
    
    // Ersten Fehler für ein bestimmtes Feld abrufen
    $firstNameError = $errors->first('name');
    
    // Prüfen, ob ein Feld Fehler hat
    $hasNameErrors = $errors->has('name');
}

Anzeigen von Validierungsfehlern in Views

In Ihren Views können Sie die Validierungsfehler wie folgt anzeigen:

<?php if ($errors->has('name')): ?>
    <div class="error"><?= $errors->first('name') ?></div>
<?php endif; ?>

Oder alle Fehler anzeigen:

<?php if ($errors->any()): ?>
    <div class="alert alert-danger">
        <ul>
            <?php foreach ($errors->all() as $error): ?>
                <li><?= $error ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

Beste Praktiken

Wiederverwendung von Validierungsregeln

Wenn Sie dieselben Validierungsregeln in mehreren Controllern verwenden, sollten Sie sie in eine separate Klasse auslagern:

class UserValidationRules
{
    public static function forCreation(): array
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|string|min:8|confirmed',
        ];
    }
    
    public static function forUpdate(int $userId): array
    {
        return [
            'name' => 'string|max:255',
            'email' => 'email|unique:users,email,' . $userId,
        ];
    }
}

Dann können Sie diese Regeln in Ihren Controllern verwenden:

public function store(Request $request): Response
{
    $this->validate($request, UserValidationRules::forCreation());
    
    // ...
}

public function update(Request $request, int $id): Response
{
    $this->validate($request, UserValidationRules::forUpdate($id));
    
    // ...
}

Validierung in Modellen

Sie können Validierungsregeln auch in Ihren Modellen definieren:

class User extends Model
{
    public static function validationRules(): array
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|string|min:8',
        ];
    }
    
    public static function updateValidationRules(int $userId): array
    {
        return [
            'name' => 'string|max:255',
            'email' => 'email|unique:users,email,' . $userId,
        ];
    }
}

Dann können Sie diese Regeln in Ihren Controllern verwenden:

public function store(Request $request): Response
{
    $this->validate($request, User::validationRules());
    
    // ...
}

public function update(Request $request, int $id): Response
{
    $this->validate($request, User::updateValidationRules($id));
    
    // ...
}

Weitere Informationen