Introduction

Laravel is a popular PHP framework known for its simplicity and elegance. One of its key features is its robust validation system, which ensures that incoming data meets specified criteria before it is processed. This blog will provide a systematic guide to Laravel’s validation features, including basic validation, custom error messages, and advanced validation techniques.

Validation Quickstart

Defining Routes

To get started with Laravel validation, you need to define routes for your application. These routes will handle the form display and data submission.

In routes/web.php, define the following routes:

use App\Http\Controllers\PostController;
Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);

The GET route displays the form for creating a new blog post, while the POST route handles form submission and data storage.

Creating the Controller

Next, create a controller to manage the routes. In the app/Http/Controllers directory, create PostController.php:

namespace App\Http\Controllers;

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

class PostController extends Controller
{
    /**
     * Show the form to create a new blog post.
     */
    public function create(): View
    {
        return view('post.create');
    }

    /**
     * Store a new blog post.
     */
    public function store(Request $request): RedirectResponse
    {
        // Validate and store the blog post...
        $validated = $request->validate([
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        // The blog post is valid...
        // Store the blog post...

        return redirect('/posts');
    }
}

Writing Validation Logic

In the store method, we use the validate method provided by the Request object to validate the incoming data. If validation fails, Laravel automatically redirects the user back to the form with error messages.

Displaying Validation Errors in Blade

When validation fails, Laravel redirects the user back to the previous URL and flashes the validation errors to the session. To display these errors in your Blade view, use the $errors variable, which is an instance of Illuminate\Support\MessageBag.

<!-- /resources/views/post/create.blade.php -->

<h1>Create Post</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- Create Post Form -->
<form method="POST" action="/post">
    @csrf
    <label for="title">Post Title</label>
    <input id="title" type="text" name="title" value="{{ old('title') }}" class="@error('title') is-invalid @enderror">
    @error('title')
        <div class="alert alert-danger">{{ $message }}</div>
    @enderror

    <label for="body">Post Body</label>
    <textarea id="body" name="body" class="@error('body') is-invalid @enderror">{{ old('body') }}</textarea>
    @error('body')
        <div class="alert alert-danger">{{ $message }}</div>
    @enderror

    <button type="submit">Create Post</button>
</form>

Customizing Error Messages

Laravel’s built-in validation rules come with default error messages stored in the lang/en/validation.php file. You can customize these messages as needed.

$messages = [
    'title.required' => 'A title is required',
    'body.required' => 'A body is required',
];

$validated = $request->validate([
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
], $messages);

Form Request Validation

For more complex validation scenarios, Laravel provides form request classes that encapsulate their own validation and authorization logic.

Creating Form Requests

Create a form request class using Artisan:

php artisan make:request StorePostRequest

In the generated class (app/Http/Requests/StorePostRequest.php), define the validation rules and authorization logic:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePostRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ];
    }
}

Authorizing Form Requests

Type-hint the form request in your controller method:

use App\Http\Requests\StorePostRequest;

public function store(StorePostRequest $request): RedirectResponse
{
    $validated = $request->validated();
    // Store the blog post...

    return redirect('/posts');
}

Advanced Validation Techniques

Conditionally Adding Rules

You can conditionally add validation rules based on certain criteria using the sometimes method:

$validator = Validator::make($request->all(), [
    'email' => 'required|email',
    'games' => 'required|numeric',
]);

$validator->sometimes('reason', 'required|max:500', function ($input) {
    return $input->games > 100;
});

Validating Arrays

To validate arrays, use dot notation:

$request->validate([
    'title' => 'required|unique:posts|max:255',
    'author.name' => 'required',
    'author.description' => 'required',
]);

Custom Validation Rules

Create custom validation rules using rule objects or closures:

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}

$request->validate([
    'name' => ['required', new Uppercase],
]);

Validation for APIs

When validating data for APIs, Laravel automatically returns a JSON response with the validation errors and a 422 status code if validation fails. Here’s how you can handle validation in an API controller:

use Illuminate\Http\Request;

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

    // If validation passes, continue processing...

    return response()->json(['message' => 'Post created successfully'], 201);
}

Conclusion

Laravel’s validation system is both powerful and flexible, allowing you to ensure the integrity of incoming data with ease. From basic validation to advanced techniques, Laravel provides all the tools you need to handle validation gracefully and efficiently. Whether you’re working with forms or APIs, Laravel’s validation features will help you maintain data quality and security.

For more detailed information on Laravel validation, refer to the official documentation.

Categorized in: