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:
php artisan make:request StoreProductRequestThis 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:
// 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 — 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:
- A request arrives at a controller method whose parameter is type-hinted with the Form Request class.
- Before the method body runs, Laravel calls
authorize()— if it returns false, the request is blocked (403). - Laravel then checks the request against
rules(). - If any rule fails, it redirects back with errors and never runs your method.
- 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?
✍️ Practice
- Generate a Form Request, move your rules into it, and type-hint it on a store method.
- Add a custom message for one rule and trigger it.
🏠 Homework
- Create Store and Update Form Requests for a resource and wire both into the controller.