Learn how to use Form Requests in Laravel to move validation logic out of your controllers. Keep your code clean, DRY, and professional with this guide.
Previously in this course, we covered introduction to Laravel validation and customizing validation error messages. Those techniques are perfect for simple forms, but as your application grows, keeping validation rules inside your controller methods leads to "fat controllers"—a common sign of technical debt.
This lesson introduces Form Requests, a powerful feature that allows you to encapsulate validation logic into dedicated classes, keeping your controllers focused strictly on handling the request flow.
When you keep validation rules directly in your controller, the store() or update() methods quickly become cluttered. If you have complex rules or need to reuse that validation logic in multiple places, your code becomes brittle and hard to maintain.
Form Requests act as a "gatekeeper." When you inject a Form Request class into your controller, Laravel automatically validates the incoming data before your controller method even executes. If the validation fails, Laravel automatically redirects the user back with the error messages. If it passes, your controller receives the validated data, clean and ready to use.
To start, let's clean up the TasksController in our Task Manager project. We’ll generate a dedicated class for validating task creation. Run the following command in your terminal:
Bashphp artisan make:request StoreTaskRequest
This generates a new file at app/Http/Requests/StoreTaskRequest.php. Open this file, and you’ll see two main methods: authorize() and rules().
The authorize() method determines if the user has permission to make this request. For now, we will return true because we haven't implemented authentication yet.
This is where you define your validation logic. Move the rules you previously defined in your controller into this array.
PHP#6A9955">// app/Http/Requests/StoreTaskRequest.php public function rules(): array { return [ 'title' => 'required|string|max:255', 'description' => 'nullable|string', ]; }
Now that the validation logic is safely tucked away in its own class, it’s time to use it. Open your TasksController.php and replace the standard Illuminate\Http\Request type-hint with your custom StoreTaskRequest.
PHP#6A9955">// app/Http/Controllers/TasksController.php use App\Http\Requests\StoreTaskRequest; public function store(StoreTaskRequest $request) { #6A9955">// If we reach this line, the data is already validated! $validated = $request->validated(); Task::create($validated); return redirect('/tasks'); }
By changing the type-hint, Laravel’s service container automatically resolves the StoreTaskRequest and runs the rules() method before your code inside store() ever runs. If the user submits an empty title, they are automatically sent back to the previous page with errors, just like before, but your controller is now much cleaner.
TasksController@store method and move the validation rules into the StoreTaskRequest class as shown above.store method becomes. This is the "clean code" standard we aim for in professional Laravel development.use statement.true in the authorize() method. If you leave it as false, your form will return a 403 Forbidden error every time you try to submit it.Form Requests are the preferred way to handle validation in production-grade Laravel apps. By centralizing validation, you ensure your controllers remain thin and readable. You've now moved from manual, inline validation to a professional structure that scales with your application.
Up next: Introduction to Authentication where we'll start securing our Task Manager by letting users sign up and log in.
Learn to customize Laravel validation error messages to provide clear, helpful feedback to your users. Master field-specific errors and language files.
Read moreLearn how to use Laravel validation to ensure data integrity. Discover how to apply rules, handle failures, and display error messages in your Blade views.
Using Form Requests for Validation
Preventing Mass Assignment
Task Manager: Securing the Application
Introduction to Route Model Binding
Updating Existing Records
Deleting Records
Using Named Routes
Task Manager: Completing CRUD Functionality
Introduction to Database Relationships
Querying Related Data
Handling File Uploads
Using Flash Messages for User Feedback
Task Manager: Adding Status and Priorities
Introduction to Artisan Commands
Debugging with Laravel Tinker
Understanding Service Providers
Using View Composers
Task Manager: Refactoring for Clean Code
Introduction to Testing
Testing Forms and Validation
Using Database Transactions
Handling Global Exceptions
Preparing for Production
Environment Security Best Practices
Managing Assets in Production
Task Manager: Deployment Preparation