Clean Controllers: Master Laravel Form Requests

Overview

Controllers often become bloated with validation rules and authorization checks that distract from the primary business logic.

Form Requests
solve this by encapsulating these concerns into a dedicated class. This promotes the Single Responsibility Principle, ensuring your controllers remain slim, readable, and focused on execution rather than data gatekeeping.

Prerequisites

To follow this guide, you should be comfortable with basic

and the
Laravel
framework. You should understand how controllers handle HTTP requests and be familiar with standard validation rules like required and min.

Key Libraries & Tools

  • Artisan CLI: The command-line interface used to scaffold new classes.
  • FormRequest Class: The base Laravel class that provides methods for authorization and validation.
  • Validator: The underlying engine that processes data against defined rules.

Code Walkthrough

First, generate your request class using

:

php artisan make:request StorePostRequest

This creates a file in app/Http/Requests. Inside, you’ll find two primary methods. The authorize method returns a boolean to determine if the user can proceed. Unlike manual controller checks, failing this automatically triggers a 403 response.

public function authorize(): bool
{
    return $this->user()->can('create', Post::class);
}

The rules method defines your data constraints. By moving these here, you can reuse the same request across different controllers or API endpoints.

public function rules(): array
{
    return [
        'title' => 'required|max:255',
        'status' => 'required|in:draft,published',
        'text' => 'required',
    ];
}

Finally, type-hint the request in your controller.

injects the validated instance, allowing you to call $request->validated() to retrieve only the safe data.

Advanced Logic with the After Hook

Sometimes validation depends on external state, like checking if a user has exceeded a post limit. The after method allows you to register closures or invokable classes that run after standard rules pass. This keeps complex, conditional logic out of your controller flow.

public function after(): array
{
    return [
        function ($validator) {
            if ($this->user()->posts()->count() > 1) {
                $validator->errors()->add('title', 'Limit reached.');
            }
        }
    ];
}

Tips & Gotchas

  • Automatic Redirects: If validation fails,
    Laravel
    automatically redirects the user back to their previous location with error messages in the session.
  • Initial False: New Form Requests default authorize to false. Always remember to update this to true or add your logic, otherwise, you will face constant 403 errors.
2 min read