Handling form input and validation is a crucial aspect of any web application. Laravel offers a powerful approach to manage this via Form Request classes, allowing you to keep your controllers clean and reuse validation logic. In this article, we'll take a comprehensive look at mastering Form Requests and validation in Laravel.
Why Use Form Request Classes?
Using traditional request validation in your controller can clutter your code and make it harder to maintain:
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|max:255',
'email' => 'required|email|unique:users',
]);
// ...
}
As your application grows, this logic becomes repetitive. Form Request classes offer:
- Separation of concerns: Validation logic resides outside controllers.
- Reusability and scalability: Use the same Form Request across multiple controllers.
- Cleaner controllers: Focus only on business logic.
Creating a Form Request
To generate a new Form Request class, use Artisan:
php artisan make:request StoreUserRequest
Laravel creates a new class in app/Http/Requests/StoreUserRequest.php
.
Basic Example
Open the generated class:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreUserRequest extends FormRequest
{
// Authorize if the user can make this request
public function authorize()
{
return true;
}
// Define your validation rules
public function rules()
{
return [
'name' => 'required|max:255',
'email' => 'required|email|unique:users',
];
}
}
Note: If authorize()
returns false
, Laravel will return a 403 Forbidden
response.
Using Form Requests in Controllers
Inject your Form Request into a controller method instead of the generic Request
:
use App\Http\Requests\StoreUserRequest;
public function store(StoreUserRequest $request)
{
// If validation fails, the user is automatically redirected.
// If validation passes, the code proceeds...
$validatedData = $request->validated();
// Use $validatedData for creating the user
User::create($validatedData);
}
You're now enjoying a clean controller and reusable validation!
Customizing Validation Messages
You may want to tailor the feedback your users receive. Override the messages()
method in your Form Request:
public function messages()
{
return [
'name.required' => 'Please provide your name.',
'email.required' => 'An email address is required.',
'email.unique' => 'This email is already registered.',
];
}
Conditional Validation and More
Form Requests are just regular PHP classes. You can use all of PHP's power to tailor your validation logic.
Example: Conditional Rules
public function rules()
{
$rules = [
'name' => 'required|string|max:255',
];
if ($this->isMethod('post')) {
$rules['email'] = 'required|email|unique:users';
}
return $rules;
}
Authorizing Requests
You can control if a user is allowed to perform a given request with the authorize()
method—especially useful for admin-only routes.
public function authorize()
{
return auth()->user()->isAdmin();
}
If this returns false
, a 403
response is sent.
Advanced: Custom Validation Logic
Sometimes, built-in rule constraints are not enough. Define your own validation logic in withValidator()
:
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->input('username') === 'forbidden') {
$validator->errors()->add('username', 'This username is not allowed!');
}
});
}
Best Practices
- Reuse Form Requests: Share them where the validation logic applies exactly.
- Keep rules descriptive and lean.
- Use dependency injection in controllers for automatic resolution.
- Use custom methods for complex validation and authorization.
Conclusion
Laravel’s Form Request classes empower you to build robust, scalable, and clean applications by centralizing validation logic and authorizations. Embrace them, and your controllers—and your team—will thank you.
Further reading:
Happy validating! 🚀