Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 9 of the Intermediate Laravel: Real-World Application Patterns course
LaravelJune 25, 20263 min read

Handling API Validation and Form Requests in Laravel

Master Laravel validation by moving logic into Form Requests. Learn to keep your API controllers thin, handle custom errors, and streamline your workflow.

LaravelAPIValidationFormRequestsBackendphp

Previously in this course, we covered resource controllers and API responses, where we learned to transform model data into consistent JSON. In this lesson, we shift our focus to the input side of the request lifecycle. Specifically, we'll learn how to move validation logic out of our controllers and into dedicated Form Request classes to maintain a clean, readable codebase.

Why Centralize Validation?

In a typical API, your controllers should be responsible for orchestrating the request—receiving the input, passing it to a service or repository, and returning a response. When you include validator logic directly inside the controller methods, you violate the Single Responsibility Principle.

As your project board grows, a TaskController might need validation for creating, updating, and assigning tasks. If all that logic sits in the controller, it quickly becomes unreadable. Form Requests allow us to encapsulate these rules, ensuring that by the time a controller method is executed, the data is already guaranteed to be valid.

Generating and Configuring Form Requests

Laravel provides an Artisan command to generate these classes. Let's create one for our task creation endpoint:

Bash
php artisan make:request StoreTaskRequest

This creates a file in app/Http/Requests. Inside, you’ll find two primary methods: authorize() and rules(). For an API, the authorize() method is where you'd check if the authenticated user has permission to perform the action (though we will revisit authorization in later modules).

Here is how we define our validation logic for a new task:

PHP
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreTaskRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true; #6A9955">// We'll handle authorization via Policies later
    }

    public function rules(): array
    {
        return [
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'project_id' => 'required|exists:projects,id',
            'due_date' => 'nullable|date|after:today',
        ];
    }
}

Handling Custom API Error Responses

By default, when validation fails, Laravel redirects users back to the previous page. Since we are building a REST API, we need it to return a JSON response instead. We achieve this by overriding the failedValidation method within our StoreTaskRequest class.

PHP
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

protected function failedValidation(Validator $validator)
{
    throw new HttpResponseException(response()->json([
        'message' => 'The given data was invalid.',
        'errors' => $validator->errors(),
    ], 422));
}

By throwing an HttpResponseException, we short-circuit the request lifecycle immediately, ensuring the controller never even sees the invalid input.

Integrating the Request into the Controller

Now that our logic is encapsulated, our controller becomes significantly thinner. We simply type-hint the StoreTaskRequest in our method signature:

PHP
public function store(StoreTaskRequest $request)
{
    #6A9955">// The request is already validated here!
    $task = $this->taskService->createTask($request->validated());

    return response()->json($task, 201);
}

This pattern—often discussed as a best practice for clean controller validation—keeps our logic modular and reusable.

Hands-on Exercise

  1. Generate a Request: Create a UpdateTaskRequest using Artisan.
  2. Define Rules: Ensure the title is optional but has a minimum length of 5 characters if provided.
  3. Standardize Errors: Implement the failedValidation override in your new request class to return a 422 status code with your custom JSON structure.
  4. Refactor: Update your TaskController@update method to use this new request class.

Common Pitfalls

  • Forgetting validated(): Many developers attempt to use $request->all() inside the controller. Always use $request->validated() to ensure you are only working with the data that passed your rules, preventing mass-assignment vulnerabilities.
  • Over-complicating authorize(): Don't try to handle complex business logic in the authorize() method. Keep it simple; use Laravel Policies for domain-specific checks.
  • Assuming JSON: If you don't override failedValidation, the API will return HTML error pages if the Accept: application/json header is missing. Always override this method to guarantee a consistent API contract.

Recap

We've moved validation logic out of the controller and into specialized Form Request classes. By overriding failedValidation, we ensure our API always returns a consistent JSON response when inputs are malformed. This keeps our controllers thin and our code easy to test, following the patterns we established when we started implementing the service layer.

Up next: We will secure our endpoints by implementing custom middleware to verify project ownership and prevent cross-user data leaks.

Previous lessonResource Controllers and API ResponsesNext lesson Implementing Middleware for API Security
Back to Blog

Similar Posts

LaravelJune 25, 20264 min read

Implementing Middleware for API Security in Laravel

Learn to build custom middleware in Laravel to enforce resource ownership. Secure your API routes by verifying user access before controllers ever execute.

Read more
LaravelJune 25, 20263 min read

Using Database Transactions in Laravel: Ensuring Data Integrity

Learn how to use database transactions in Laravel to ensure your data remains consistent. Stop partial updates by mastering atomic operations with DB::transaction.

Part of the course

Intermediate Laravel: Real-World Application Patterns

intermediate · Lesson 9 of 58

  1. 1

    Architecting for Maintainability

    3 min
  2. 2

    Implementing the Service Layer

    3 min
  3. 3

    Repository Pattern Fundamentals

    3 min
Read more
LaravelJune 25, 20263 min read

Resource Controllers and API Responses in Laravel

Learn how to use Laravel API resources to transform model data and return consistent, clean JSON responses for your RESTful applications.

Read more
  • 4

    Project Board Domain Modeling

    3 min
  • 5

    Advanced Eloquent Scopes and Accessors

    4 min
  • 6

    Service-Oriented Task Management

    3 min
  • 7

    REST API Fundamentals with Sanctum

    3 min
  • 8

    Resource Controllers and API Responses

    3 min
  • 9

    Handling API Validation and Form Requests

    3 min
  • 10

    Implementing Middleware for API Security

    4 min
  • 11

    Database Transactions for Data Integrity

    3 min
  • 12

    Error Handling and Global Exceptions

    3 min
  • 13

    Introduction to Laravel Events and Listeners

    Coming soon
  • 14

    Asynchronous Processing with Queues

    Coming soon
  • 15

    Job Chaining and Batching

    Coming soon
  • 16

    Feature Testing Fundamentals

    Coming soon
  • 17

    Mocking Services and Repositories in Tests

    Coming soon
  • 18

    Testing Events and Jobs

    Coming soon
  • 19

    Database Factories and Seeding

    Coming soon
  • 20

    API Versioning Strategies

    Coming soon
  • 21

    Advanced Request Filtering and Sorting

    Coming soon
  • 22

    Handling File Uploads in REST APIs

    Coming soon
  • 23

    Real-time Notifications with Broadcasting

    Coming soon
  • 24

    Using Observers for Model Lifecycle Hooks

    Coming soon
  • 25

    Implementing Policies for Authorization

    Coming soon
  • 26

    Customizing Authentication Guards

    Coming soon
  • 27

    Rate Limiting API Endpoints

    Coming soon
  • 28

    Eloquent Performance Optimization

    Coming soon
  • 29

    Caching Strategies for Performance

    Coming soon
  • 30

    Using Traits for Code Reuse

    Coming soon
  • 31

    Advanced Dependency Injection with Service Providers

    Coming soon
  • 32

    Command Line Tools with Artisan

    Coming soon
  • 33

    Scheduled Tasks and Cron Jobs

    Coming soon
  • 34

    Integrating Third-Party Services

    Coming soon
  • 35

    Handling Webhooks

    Coming soon
  • 36

    Logging and Monitoring

    Coming soon
  • 37

    Database Migrations Best Practices

    Coming soon
  • 38

    Advanced Testing: Integration Tests

    Coming soon
  • 39

    Testing API Authentication

    Coming soon
  • 40

    Code Quality and Static Analysis

    Coming soon
  • 41

    Project Structure for Large Applications

    Coming soon
  • 42

    Environment and Configuration Management

    Coming soon
  • 43

    Deploying Laravel Applications

    Coming soon
  • 44

    Database Indexing Strategies

    Coming soon
  • 45

    Using Value Objects

    Coming soon
  • 46

    Strategy Pattern for Business Rules

    Coming soon
  • 47

    Advanced Queue Monitoring

    Coming soon
  • 48

    Building a Search API

    Coming soon
  • 49

    Handling Concurrency and Race Conditions

    Coming soon
  • 50

    API Documentation with OpenAPI

    Coming soon
  • 51

    Testing with Test Doubles

    Coming soon
  • 52

    Implementing Multi-Tenancy

    Coming soon
  • 53

    Refactoring Legacy Code

    Coming soon
  • 54

    Using Middleware for Feature Flags

    Coming soon
  • 55

    Building Reusable Packages

    Coming soon
  • 56

    Performance Profiling

    Coming soon
  • 57

    Secure API Design

    Coming soon
  • 58

    Event Sourcing Concepts

    Coming soon
  • View full course