Laravel

Creating Form Request Classes in Laravel: The Right Way to Handle Validation

Every Laravel application eventually needs to validate user input. Whether you're processing a registration form, handling an API payload, or accepting data from an external service, the validation layer is your first line of defense against bad data. Laravel's Form Request classes offer an elegant solution that keeps your controllers lean and your validation logic organized.

Rather than cramming validation rules directly into controller methods, Form Requests let you extract that behavior into dedicated classes. This approach has become standard practice in well-structured Laravel applications.

The make:request Command in Action

The artisan CLI handles the heavy lifting. Open your terminal, navigate to your Laravel project, and run:

`php artisan make:request ProductPostRequest`

Laravel immediately creates a new file at `app/Http/Requests/ProductPostRequest.php`. The file contains a pre-built class that extends Laravel's FormRequest base class, complete with the two methods you'll work with most.

Quick take:

  • Command generates files in app/Http/Requests/
  • Class extends Illuminate\Foundation\Http\FormRequest
  • Authorize() controls whether the request proceeds
  • Rules() returns validation constraints as an array
  • Attempting to create a duplicate class throws an error

The generated file includes a namespace declaration, the necessary use statement for FormRequest, and two stub methods waiting for your logic.

Understanding the Two Core Methods

The authorize() method acts as a gatekeeper. It determines whether the authenticated user should be allowed to submit this particular request. For public forms, simply return true. For restricted resources, add your permission checks here—perhaps verifying that the user owns the record they're trying to update.

The rules() method is where your validation logic lives. This method must return an array where keys correspond to input field names and values define the constraints. Laravel ships with dozens of built-in validation rules covering common scenarios like required fields, string length limits, email formats, and uniqueness checks against your database.

How the Class Structure Works

The typical request class looks like this:

“`php

<?php

Namespace App\Http\Requests;

Use Illuminate\Foundation\Http\FormRequest;

Class ProductPostRequest extends FormRequest

{

Public function authorize()

{

Return true;

}

Public function rules()

{

Return [

'title' => 'required|string|min:3|max:255',

'price' => 'required|numeric|min:0',

'category_id' => 'required|exists:categories,id',

];

}

}

“`

When validation fails, Laravel automatically redirects the user back with errors flashed to the session. For API endpoints, it returns a properly formatted JSON response with a 422 status code.

Why This Approach Improves Your Codebase

Separating validation from controllers offers concrete benefits. Your controller methods become shorter and focused purely on business logic. When validation rules change, you edit one file rather than hunting through multiple controllers. Testing becomes more straightforward since you can unit test validation rules independently. The overall structure becomes more maintainable as your application grows.

Consider a real scenario: say you are building an e-commerce platform and need to validate product submissions. Your ProductPostRequest might enforce that product names are 3 to 100 characters, prices are positive decimals, descriptions are optional but limited to 2000 characters, and category IDs reference existing records. When marketing requests a new validation rule—say, product names cannot contain promotional phrases—you update one file. Your controllers never need touching.

Our Analysis: When to Choose Form Requests

This pattern works best when handling complex validation scenarios or when the same validation logic applies across multiple endpoints. Small, simple forms with minimal rules might not need the extra file, but any validation exceeding a handful of fields benefits from this approach.

The trade-off is a slight increase in file count versus improved maintainability. For production applications expected to grow, the organization payoff typically outweighs the minimal overhead.

Common Validation Rules You'll Use

Laravel's validation library covers most needs. Frequently used rules include required, string, numeric, min, max, email, unique, and exists. Custom validation rules can be created when built-in options don't match your specific requirements, either as inline callbacks or dedicated rule classes.

What to Watch Next

Laravel continues improving Form Request functionality with each release. Pay attention to nested validation syntax for complex data structures and the integration between Form Requests and API resource classes. If you're starting a new Laravel project, make Form Requests your default approach for any non-trivial user input.

Key takeaways

  • The make:request command instantly generates validation classes in app/Http/Requests/
  • Fill in authorize() for permissions and rules() for your validation constraints
  • Form Request classes keep controllers clean and validation reusable across your application
  • Laravel handles error responses automatically for both web and API routes

Frequently asked questions

Can I use Form Requests with API routes?

Yes, they work identically for API and web routes. Laravel automatically returns JSON error responses for API requests.

How do I access validated data after the request passes validation?

Use $request->validated() to retrieve a clean array of validated data, or access individual fields with $request->field_name.

What happens when validation fails?

Laravel redirects back with errors and old input for web requests, or returns a 422 JSON response for API requests.

Can I create custom validation rules?

Yes, create custom rule classes with `php artisan make:rule RuleName`, or define inline custom rules using Rule::custom(function()).

How do I share validation rules between multiple requests?

Create a base request class with shared rules, then extend it in specific request classes to reuse the logic.

Related