Laravel Form Requests help you keep your controllers clean by centralizing validation logic. Learn how to implement them in this practical PHP tutorial.
When I first started with Laravel, I put all my validation logic inside my controllers. It seemed fine at first—just a few lines of $request->validate()—but as my projects grew, those controllers turned into massive, unreadable files. If you're currently staring at a 100-line store method, you're exactly where I was three years ago.
The solution isn't just "better coding habits"; it's using laravel form requests to delegate the heavy lifting. By moving validation to dedicated classes, you gain cleaner controllers and reusable logic that makes debugging significantly faster.
We’ve all been there: you’re writing a UserController@store method, and suddenly you have 15 lines of validation rules before you even touch the database. It’s messy. It violates the Single Responsibility Principle because your controller is now managing input validation and business logic.
When we first tried to solve this by moving validation into custom service classes, we ended up with a different problem: code duplication. Every time we needed to update a user, we had to remember to call the service. Switching to laravel form requests solved this because the validation happens automatically before the controller method is even executed.
To create a form request, use the Artisan CLI. In your terminal, run:
Bashphp artisan make:request StoreUserRequest
This generates a file in app/Http/Requests. Inside, you’ll find two primary methods: authorize() and rules().
The authorize() method determines if the user is allowed to perform the request. If you’re building a simple app, you can often just return true here, but for production, this is where you’d check permissions. The rules() method is where the real magic happens. It’s just like the standard validate array you’re used to:
PHPpublic function rules(): array { return [ 'name' => 'required|string|max:255', 'email' => 'required|email|unique:users,email', 'password' => 'required|confirmed|min:8', ]; }
The best part about this laravel tutorial approach is how clean your controller becomes. You don't need to manually call the validator. Just type-hint your new Request class in the controller method signature, and Laravel handles the rest.
PHPpublic function store(StoreUserRequest $request) { #6A9955">// If we reached here, the data is already validated! $validated = $request->validated(); User::create($validated); return redirect()->route('users.index'); }
If the validation fails, Laravel automatically redirects the user back to the previous page with all the error messages stored in the session. You don't have to write a single line of redirection logic. It just works.
Sometimes, a simple rule isn't enough. You might need to change validation rules based on the user's role or the current environment. Because Form Requests are just standard PHP classes, you can inject dependencies into the constructor or use the prepareForValidation() method to manipulate input before the rules are even applied.
For example, if you need to sanitize a phone number before validating it, you can do this:
PHPprotected function prepareForValidation(): void { $this->merge([ 'phone' => str_replace(['-', ' '], '', $this->phone), ]); }
This level of control is exactly why I recommend moving away from inline laravel validation as soon as you have more than three or four fields. It keeps your code predictable.
Once you’ve mastered request validation, you’ll likely want to clean up other parts of your stack. If you're handling complex data transformations, you might find that Mastering Laravel DTOs: Type-Safe Data Handling for Clean Code is a great next step to keep your data structures consistent.
If you are building an API, you might also want to look into Mastering Laravel API Resources: A Guide to Clean JSON Responses to ensure that the data you send back is as clean as the data you receive.
Yes, but you’ll need to handle conditional rules. You can access the route parameters using $this->route('user') inside your rules() method to ignore the unique email constraint if the record already exists.
You can add a messages() method to your Form Request class and return an array of custom messages. It’s perfect for providing a better user experience.
Maybe. If it's a tiny project, inline validate() is fine. But once you're building out a full application, the overhead of creating a class pays for itself within about two days of development time.
I’m still refining my own approach to these requests. Sometimes I find myself creating too many classes for simple actions, which can lead to "class sprawl." If you find yourself doing that, don't be afraid to group related validation logic or stick to standard validation for smaller, one-off features. There’s no point in over-engineering a simple form.
Mastering Laravel Eloquent scopes allows you to write cleaner database queries by encapsulating complex logic into reusable, readable model methods.
Read more