Navigation

Laravel

How to properly use Form Requests for API validation

Use Laravel Form Requests for clean API validation with automatic error responses, authorization logic, and reusable validation rules.

Table Of Contents

Problem

Your API controllers are cluttered with validation logic and you need a cleaner way to handle validation with proper JSON error responses.

Solution

Create Form Request classes that automatically handle API validation:

// Create Form Request
php artisan make:request CreateUserRequest

// app/Http/Requests/CreateUserRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class CreateUserRequest extends FormRequest
{
    public function authorize()
    {
        return true; // or implement authorization logic
    }
    
    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|string|min:8|confirmed',
            'role' => 'sometimes|in:admin,user,moderator'
        ];
    }
    
    public function messages()
    {
        return [
            'name.required' => 'The name field is required.',
            'email.unique' => 'This email is already registered.',
            'password.confirmed' => 'Password confirmation does not match.',
        ];
    }
}

Use in controller:

// Controller
public function store(CreateUserRequest $request)
{
    // Validation happens automatically
    // $request->validated() contains only validated data
    
    $user = User::create($request->validated());
    
    return response()->json($user, 201);
}

Why It Works

Form Requests automatically validate incoming data and return 422 JSON responses with validation errors for API requests. Laravel detects API requests (via Accept headers or /api routes) and formats error responses appropriately without additional code.

Advanced Form Request features:

class UpdateUserRequest extends FormRequest
{
    public function authorize()
    {
        // Only allow users to update their own profile
        return $this->user()->id === $this->route('user')->id;
    }
    
    public function rules()
    {
        $userId = $this->route('user')->id;
        
        return [
            'name' => 'sometimes|string|max:255',
            'email' => "sometimes|email|unique:users,email,{$userId}",
            'avatar' => 'sometimes|image|max:2048',
        ];
    }
    
    protected function prepareForValidation()
    {
        // Transform data before validation
        $this->merge([
            'name' => ucwords($this->name),
        ]);
    }
    
    public function withValidator($validator)
    {
        // Custom validation logic
        $validator->after(function ($validator) {
            if ($this->somethingElseIsInvalid()) {
                $validator->errors()->add('field', 'Something is wrong!');
            }
        });
    }
}

Related: Laravel Collections: Beyond Basic Array Operations | Laravel Events and Listeners: Building Decoupled Applications | Laravel API Development: Best Practices and Security | Level Up Your Laravel Validation: Advanced Tips & Tricks | Custom Laravel Validation Rules: Beyond the Basics

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Laravel