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

# Validation

> How to validate incoming request data in Laravel using the validate method and form request classes.

## What is validation?

Validation is the process of verifying that data submitted by the user meets the format and rules your application expects. Laravel provides a simple, expressive validation system built into the request object, with no third-party packages required.

```mermaid theme={null}
flowchart TD
    A["HTTP request received"] --> B["Apply validation rules"]
    B --> C{{"Validation<br>passed?"}}
    C -->|"Success"| D["Retrieve validated data"]
    D --> E["Execute controller logic"]
    E --> F["Success response"]
    C -->|"Failure<br>(web request)"| G["Redirect back<br>Store errors in session"]
    C -->|"Failure<br>(API request)"| H["422 Unprocessable Entity<br>JSON error response"]
```

## Validating in a controller

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

The most straightforward way to validate incoming data is to call `$request->validate()` inside a controller method. If validation fails, Laravel automatically redirects the user back to the previous page and stores the error messages in the session.

First, define your routes:

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

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

Then write the 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',
        ]);

        // Save the post using validated data...

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

Pass an array to `validate` where each key is a field name and each value is the validation rules for that field. You can express rules either as a pipe-delimited string or as an array:

```php theme={null}
// Pipe-delimited
'title' => 'required|string|max:255',

// Array form
'title' => ['required', 'string', 'max:255'],
```

### Common validation rules

| Rule           | Description                                                         |
| -------------- | ------------------------------------------------------------------- |
| `required`     | The field must be present and non-empty                             |
| `string`       | The field must be a string                                          |
| `email`        | The field must be a valid email address                             |
| `min:value`    | The string length or numeric value must be at least the given value |
| `max:value`    | The string length or numeric value must not exceed the given value  |
| `unique:table` | The value must be unique in the given database table                |
| `nullable`     | The field may be `null`                                             |
| `integer`      | The field must be an integer                                        |
| `boolean`      | The field must be `true`, `false`, `1`, or `0`                      |
| `date`         | The field must be a valid date                                      |
| `confirmed`    | The field must match a corresponding `field_confirmation` field     |

<Info>
  For the full list of available validation rules, see the [official documentation](https://laravel.com/docs/validation#available-validation-rules).
</Info>

### Using validated data

The `validate` method returns only the data that passed validation. Use this array directly — it contains nothing more than what you explicitly declared:

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

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

## Displaying errors in Blade

When validation fails, Laravel makes an `$errors` variable available in every view. The `ShareErrorsFromSession` middleware in the `web` middleware group handles this automatically.

### Display all errors

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

### Display errors per field

Use the `@error` directive to show an inline error message for a specific field:

```blade theme={null}
<label for="title">Title</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>
  Use `old('field')` to repopulate form fields with the user's previous input after a validation failure.
</Tip>

## Form request classes

### When to use them

When validation logic becomes complex, extract it into a dedicated "form request" class. A form request encapsulates both the validation rules and the authorization check for a request.

```mermaid theme={null}
flowchart TD
    A["Controller method called"] --> B["FormRequest instance created"]
    B --> C["Run authorize() method"]
    C --> D{{"Authorized?"}}
    D -->|"false"| E["403 Forbidden response"]
    D -->|"true"| F["Run rules() method"]
    F --> G["Execute validation"]
    G --> H{{"Validation<br>passed?"}}
    H -->|"Failure"| I["Validation<br>error response"]
    H -->|"Success"| J["Controller method executed"]
```

### Creating a form request

Use the `make:request` Artisan command:

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

This creates `app/Http/Requests/StorePostRequest.php`:

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

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePostRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @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',
        ];
    }
}
```

### The `rules()` method

Return your validation rules as an array, using the same format as `$request->validate()`.

### The `authorize()` method

Return `true` to allow the request, or `false` to automatically return a 403 response. You can check the authenticated user here. For tutorials, returning `true` is fine.

<Warning>
  If `authorize` returns `false`, Laravel returns a 403 Forbidden response and the controller method is never called.
</Warning>

### Using the form request in a controller

Type-hint the form request class on your controller method. Laravel validates and authorizes the request before your method is called, so you can skip writing any validation code inside the method:

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

class PostController extends Controller
{
    public function store(StorePostRequest $request): RedirectResponse
    {
        // Execution only reaches here if validation passed

        $validated = $request->validated();

        Post::create($validated);

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

Call `$request->validated()` to retrieve only the data that passed validation.

## Practical example: a post creation form

Here is the full flow — from displaying a form to validating and saving the data.

<Steps>
  <Step title="Define routes">
    ```php theme={null}
    use App\Http\Controllers\PostController;

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

  <Step title="Create a form request">
    ```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="Implement the controller">
    ```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="Create the Blade template">
    ```blade theme={null}
    {{-- resources/views/posts/create.blade.php --}}

    <h1>New 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">Title</label>
            <input
                id="title"
                type="text"
                name="title"
                value="{{ old('title') }}"
            />
            @error('title')
                <span>{{ $message }}</span>
            @enderror
        </div>

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

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

<Info>
  Always include the `@csrf` directive in your Blade forms. Without it, Laravel returns a 419 error.
</Info>

## Next steps

<Card title="Controllers" icon="server" href="/en/controllers">
  Review how to organize request handling logic in controller classes.
</Card>
