> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Validatie

> Leer hoe je formulierinvoer valideert met de validatiefunctionaliteit van Laravel.

## Wat is validatie

Validatie is het controleren of de gegevens die een gebruiker verstuurt voldoen aan het verwachte formaat en de gestelde voorwaarden.
Laravel biedt een eenvoudige maar krachtige validatiefunctionaliteit via de `validate` methode van het request-object of via speciale form request-klassen.

```mermaid theme={null}
flowchart TD
    A["HTTP-request ontvangen"] --> B["Validatieregels toepassen"]
    B --> C{{"Validatie<br>geslaagd?"}}
    C -->|"Geslaagd"| D["Gevalideerde data ophalen"]
    D --> E["Controllerlogica uitvoeren"]
    E --> F["Succesresponse"]
    C -->|"Mislukt<br>(webrequest)"| G["Redirect naar vorig scherm<br>Fouten opslaan in sessie"]
    C -->|"Mislukt<br>(API-request)"| H["422 Unprocessable Entity<br>JSON-foutresponse"]
```

## Validatie in de controller

### `$request->validate()` gebruiken

De eenvoudigste manier om te valideren is door `$request->validate()` aan te roepen in een controllermethode.
Als de validatie mislukt, stuurt Laravel de gebruiker automatisch terug naar het vorige scherm en slaat het de foutinformatie op in de sessie.

Definieer de routes.

```php theme={null}
use App\Http\Controllers\PostController;

Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);
```

Maak de controller.

```php theme={null}
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    public function create(): View
    {
        return view('post.create');
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'body'  => 'required|string',
            'email' => 'required|email',
        ]);

        // Sla de post op met de gevalideerde data...

        return redirect('/posts');
    }
}
```

Aan de `validate` methode geef je een array door met veldnamen als sleutels en regels als waarden.
Regels kun je scheiden met een pipe `|` of opgeven als array.

```php theme={null}
// Gescheiden met pipes
'title' => 'required|string|max:255',

// Als array
'title' => ['required', 'string', 'max:255'],
```

### Belangrijke validatieregels

| Regel                              | Beschrijving                                                            |
| ---------------------------------- | ----------------------------------------------------------------------- |
| `required`                         | De waarde moet aanwezig zijn en mag niet leeg zijn                      |
| `string`                           | De waarde moet een string zijn                                          |
| `email`                            | De waarde moet een geldig e-mailadresformaat hebben                     |
| `min:waarde`                       | De stringlengte of het getal moet minimaal de opgegeven waarde zijn     |
| `max:waarde`                       | De stringlengte of het getal mag maximaal de opgegeven waarde zijn      |
| `unique:tabel`                     | De waarde moet uniek zijn in de opgegeven tabel                         |
| `nullable`                         | De waarde mag ook `null` zijn                                           |
| `integer`                          | De waarde moet een geheel getal zijn                                    |
| `boolean`                          | De waarde moet een boolean zijn (`true`/`false`, `1`/`0`, enz.)         |
| `date`                             | De waarde moet een geldig datumformaat hebben                           |
| `confirmed`                        | De waarde moet overeenkomen met het veld `veldnaam_confirmation`        |
| `array_keys:sleutel1,sleutel2,...` | De sleutels van de array mogen alleen uit de opgegeven sleutels bestaan |

### Uitgebreide validatie van e-mailadressen

Aan de `email` regel kun je parameters toevoegen die de validatiemethode bepalen.

```php theme={null}
'email' => ['email:rfc,dns'],
```

`rfc` valideert dat het formaat voldoet aan de RFC, en `dns` valideert dat het domein van het e-mailadres een geldig MX-record heeft. `dns` voert daadwerkelijk een DNS lookup uit, maar bepaalt niet of de individuele mailbox bestaat.

Je kunt dezelfde validatie ook schrijven met de fluent Rule builder.

```php theme={null}
use Illuminate\Validation\Rule;

$request->validate([
    'email' => [
        'required',
        Rule::email()
            ->rfcCompliant(strict: false)
            ->validateMxRecord()
            ->preventSpoofing(),
    ],
]);
```

De `dns` validator voert daadwerkelijk een DNS lookup uit en controleert of het domein van het e-mailadres een geldig MX-record heeft. Hij bepaalt echter niet of de individuele mailbox bestaat.

Om in tests niet afhankelijk te zijn van live DNS lookups, kun je de `dns` lookup faken met `Validator::fakeDnsLookups`. Andere opgegeven validaties, zoals `rfc`, worden gewoon uitgevoerd.

```php theme={null}
use Illuminate\Support\Facades\Validator;

Validator::fakeDnsLookups();
```

Zo kun je regels als de volgende testen terwijl je de bestaande validatieregels blijft gebruiken.

```php theme={null}
'email' => ['required', 'email:rfc,dns'],
```

<Warning>
  Voor de validatie van `dns` en `spoof` is de PHP-extensie `intl` vereist.
</Warning>

### Arraysleutels valideren

De `array_keys` regel valideert dat de waarde een PHP-array is en dat alle sleutels voorkomen in de opgegeven lijst. Geef minimaal één sleutel op.

```php theme={null}
'user' => ['array_keys:name,username'],
```

Als je rule-objecten gebruikt, kun je dit opgeven met de `Rule::arrayKeys` methode.

```php theme={null}
use Illuminate\Validation\Rule;

'user' => [Rule::arrayKeys('name', 'username')],
```

<Info>
  Alle beschikbare validatieregels vind je in de [officiële documentatie](https://laravel.com/docs/validation#available-validation-rules).
</Info>

### Gevalideerde data gebruiken

De returnwaarde van de `validate` methode is een array die alleen de data bevat die de validatie heeft doorstaan.
Je kunt deze veilig gebruiken als betrouwbare data.

```php theme={null}
$validated = $request->validate([
    'title' => 'required|string|max:255',
    'body'  => 'required|string',
]);

// $validated heeft de vorm ['title' => '...', 'body' => '...']
Post::create($validated);
```

## Fouten weergeven in Blade-templates

Als de validatie mislukt, maakt Laravel de variabele `$errors` automatisch beschikbaar in alle views.
De `ShareErrorsFromSession` middleware, die deel uitmaakt van de `web` middlewaregroep, zorgt hiervoor.

### Alle fouten in een lijst weergeven

```blade theme={null}
@if ($errors->any())
    <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
@endif
```

### Fouten per veld weergeven

Met de `@error` directive kun je fouten voor een specifiek veld inline weergeven.

```blade theme={null}
<label for="title">Titel</label>

<input
    id="title"
    type="text"
    name="title"
    value="{{ old('title') }}"
    class="@error('title') is-invalid @enderror"
/>

@error('title')
    <div class="error-message">{{ $message }}</div>
@enderror
```

<Tip>
  Met `old('veldnaam')` kun je de door de gebruiker ingevoerde waarde opnieuw in het formulier tonen nadat de validatie is mislukt.
</Tip>

## Form requests

### Wat is een form request

Wordt je validatielogica complexer, dan is het effectief om deze onder te brengen in een "form request"-klasse.
Een form request is een aangepaste request-klasse die validatie- en autorisatielogica bundelt in één klasse.

```mermaid theme={null}
flowchart TD
    A["Controllermethode aangeroepen"] --> B["FormRequest-instantie aanmaken"]
    B --> C["authorize()-methode uitvoeren"]
    C --> D{{"Autorisatie OK?"}}
    D -->|"false"| E["403 Forbidden-response"]
    D -->|"true"| F["rules()-methode uitvoeren"]
    F --> G["Validatie uitvoeren"]
    G --> H{{"Validatie<br>geslaagd?"}}
    H -->|"Mislukt"| I["Validatie-<br>foutresponse"]
    H -->|"Geslaagd"| J["Controllermethode uitvoeren"]
```

### Een form request maken

Genereer een form request-klasse met het `make:request` Artisan-commando.

```shell theme={null}
php artisan make:request StorePostRequest
```

Het bestand `app/Http/Requests/StorePostRequest.php` wordt gegenereerd.

```php theme={null}
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePostRequest extends FormRequest
{
    /**
     * Bepaal of de gebruiker gemachtigd is dit request uit te voeren
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Geef de validatieregels terug die op dit request van toepassing zijn
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            'title' => 'required|string|max:255',
            'body'  => 'required|string',
            'email' => 'required|email|unique:posts',
        ];
    }
}
```

### De `rules()` methode

Geeft de validatieregels terug als array. Dit is hetzelfde formaat als de array die je doorgeeft aan de `validate` methode in de controller.

### De `authorize()` methode

Bepaalt of de gebruiker gemachtigd is om dit request uit te voeren.
Geef je `true` terug, dan is de autorisatie in orde; geef je `false` terug, dan wordt automatisch een 403-response teruggegeven.

Wil je alleen geauthenticeerde gebruikers toestaan, dan kun je dat controleren met `auth()->check()`.
In een tutorial volstaat het om `true` terug te geven.

<Warning>
  Als de `authorize` methode `false` teruggeeft, wordt de controllermethode niet uitgevoerd en wordt er een 403 Forbidden-response teruggegeven.
</Warning>

### Injecteren in de controller

Een form request gebruik je door hem simpelweg als type hint op te geven in de controllermethode.
De validatie wordt uitgevoerd voordat de controller wordt aangeroepen, dus je hoeft geen validatiecode in de methode te schrijven.

```php theme={null}
use App\Http\Requests\StorePostRequest;

class PostController extends Controller
{
    public function store(StorePostRequest $request): RedirectResponse
    {
        // Op dit punt is de data al gevalideerd

        $validated = $request->validated();

        Post::create($validated);

        return redirect('/posts');
    }
}
```

Met `$request->validated()` haal je alleen de gevalideerde data op.

## Complexiteit en lengte van wachtwoorden instellen

Met het `Password` rule-object kun je de complexiteit en de minimale en maximale lengte van wachtwoorden in één keer opgeven.

```php theme={null}
use Illuminate\Validation\Rules\Password;

Password::min(16)
    ->max(256)
    ->letters()
    ->mixedCase()
    ->numbers()
    ->symbols();
```

`min()` bepaalt het minimale aantal tekens, `max()` het maximale. Door `max()` op te geven kun je complexe wachtwoorden toestaan en tegelijk expliciet een bovengrens stellen voor opslag of integratie met externe diensten.

## Praktijkvoorbeeld: een postformulier maken en opslaan

Dit is de complete flow van het weergeven van het formulier tot het versturen, valideren en opslaan.

<Steps>
  <Step title="Routes definiëren">
    ```php theme={null}
    use App\Http\Controllers\PostController;

    Route::get('/posts/create', [PostController::class, 'create']);
    Route::post('/posts', [PostController::class, 'store']);
    ```
  </Step>

  <Step title="Een form request maken">
    ```shell theme={null}
    php artisan make:request StorePostRequest
    ```

    ```php theme={null}
    public function rules(): array
    {
        return [
            'title' => 'required|string|max:255',
            'body'  => 'required|string',
        ];
    }

    public function authorize(): bool
    {
        return true;
    }
    ```
  </Step>

  <Step title="De controller implementeren">
    ```php theme={null}
    use App\Http\Requests\StorePostRequest;
    use App\Models\Post;

    class PostController extends Controller
    {
        public function create(): View
        {
            return view('posts.create');
        }

        public function store(StorePostRequest $request): RedirectResponse
        {
            Post::create($request->validated());

            return redirect('/posts');
        }
    }
    ```
  </Step>

  <Step title="Een Blade-template maken">
    ```blade theme={null}
    {{-- resources/views/posts/create.blade.php --}}

    <h1>Nieuwe post</h1>

    @if ($errors->any())
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    @endif

    <form method="POST" action="/posts">
        @csrf

        <div>
            <label for="title">Titel</label>
            <input
                id="title"
                type="text"
                name="title"
                value="{{ old('title') }}"
            />
            @error('title')
                <span>{{ $message }}</span>
            @enderror
        </div>

        <div>
            <label for="body">Inhoud</label>
            <textarea id="body" name="body">{{ old('body') }}</textarea>
            @error('body')
                <span>{{ $message }}</span>
            @enderror
        </div>

        <button type="submit">Posten</button>
    </form>
    ```
  </Step>
</Steps>

<Info>
  Neem in Blade-formulieren altijd de `@csrf` directive op. Zonder CSRF-token geeft Laravel een 419-fout terug.
</Info>

## Volgende stap

<Card title="HTTP-requests" icon="arrow-up-from-bracket" href="/nl/requests">
  Blik terug op hoe je data ophaalt met het request-object.
</Card>


## Related topics

- [Laravel Prompts](/nl/prompts.md)
- [HTTP-tests](/nl/http-tests.md)
- [Laravel MCP](/nl/mcp.md)
- [Custom validatieregels](/nl/advanced/custom-validation-rules.md)
- [⚡Introductie van Livewire 4 — reactieve UI's bouwen zonder JavaScript](/nl/blog/livewire-introduction.md)
