Advanced LaravelExtra· 35 min read

Form Request Validation

Move validation out of your controller into its own tidy class — the idiomatic, job-expected way to validate input in Laravel.

What you will learn

  • Generate a Form Request class
  • Define rules and custom messages
  • Use it to validate a controller automatically

Why move validation out of the controller?

Earlier you validated inside the controller with $request->validate([...]). That works, but as rules grow the controller gets cluttered, and the same rules often need to be reused on both a create and an update form. A Form Request is a small dedicated class whose only job is to hold the validation rules for one kind of request. The controller stays clean, and the rules live in one reusable place.

Step 1 — generate the class

Artisan scaffolds the file for you:

Generate a Form Request class
php artisan make:request StoreProductRequest

This creates app/Http/Requests/StoreProductRequest.php. By convention the name starts with the action (Store, Update) and ends with Request, so its purpose is obvious at a glance.

Step 2 — fill in two methods

The generated class has two methods you fill in. authorize() decides who may make this request, and rules() lists the validation rules — the exact same rule strings you already know:

Rules, authorization and friendly messages in one place
// app/Http/Requests/StoreProductRequest.php
public function authorize(): bool
{
    return true;   // anyone may submit (tighten later with policies)
}

public function rules(): array
{
    return [
        'name'  => 'required|max:100',
        'price' => 'required|numeric|min:0',
    ];
}

public function messages(): array
{
    return [
        'name.required'  => 'Please give the product a name.',
        'price.numeric'  => 'Price must be a number.',
    ];
}

Reading it: authorize() returns true so every visitor is allowed for now (you can return a permission check here later). rules() returns the field rules exactly as before. The optional messages() method lets you replace Laravel’s default error text with your own wording — name.required targets the "required" rule on the name field.

Step 3 — use it in the controller

Now the magic: instead of Request, you type-hint your new class on the controller method. Type-hinting means writing the class name before the parameter so Laravel knows to hand you that object. Laravel then validates automatically before your method even runs:

The controller method is now tiny
// the controller — notice the parameter type
public function store(StoreProductRequest $request)
{
    // if we reach here, validation already passed
    Product::create($request->validated());
    return redirect('/products');
}

Because the parameter is typed as StoreProductRequest, Laravel runs that class’s rules first. If anything fails, it redirects back to the form with the error messages — your method body never runs. If everything passes, $request->validated() gives you just the clean, validated fields to save. The controller shrank to two lines.

Note: Output: Submit with an empty name → the user is sent back to the form and sees: "Please give the product a name." (your custom message). Submit valid data → the product saves and the browser redirects to /products.

How a Form Request runs, in order:

  1. A request arrives at a controller method whose parameter is type-hinted with the Form Request class.
  2. Before the method body runs, Laravel calls authorize() — if it returns false, the request is blocked (403).
  3. Laravel then checks the request against rules().
  4. If any rule fails, it redirects back with errors and never runs your method.
  5. If all rules pass, your method runs and $request->validated() returns the clean data.

Tip: Reuse pays off: create a StoreProductRequest and an UpdateProductRequest, or share one request between both forms. Either way the rules live outside the controller, ready to reuse and easy to test.

Q. When does a Form Request run its validation rules?

Answer: Type-hinting a Form Request makes Laravel run authorize() and rules() before your method body — failures redirect back with errors automatically.

✍️ Practice

  1. Generate a Form Request, move your rules into it, and type-hint it on a store method.
  2. Add a custom message for one rule and trigger it.

🏠 Homework

  1. Create Store and Update Form Requests for a resource and wire both into the controller.
Want to learn this with a mentor?

CodingClave runs guided, project-based training (28-day, 45-day & 6-month batches).

Explore Training →