Laravel Form Request Validation: Rules, Custom Rules, and Error Handling

January 15, 2024 · 6 min read

2026 UPDATE - LARAVEL 13
We’re excited to announce that we have updated all of our blog post examples to reflect the new Laravel 13 version! Our previous examples were based on Laravel 10, but with the release of Laravel 13, we wanted to ensure that our readers have access to the most up-to-date information and examples.
Preventing unauthorized entry to your site
In the journey of building an app with Laravel, form requests are your safeguard, ensuring that the content your users contribute is in pair with the standards you’ve set. Laravel’s validation rules enforce these standards, guarding against invalid data.
We will combine the concept of form requests with some common validation rules to illustrate how you can maintain the quality and integrity of your blog’s content.
Creating a Form Request
Let’s start by creating a form request for storing blog posts. This request will ensure that the posts meet our criteria before they’re saved to the database.
php artisan make:request StorePostRequest
This command generates a StorePostRequest class in the app/Http/Requests directory.
Defining Validation Rules in the Form Request
In our StorePostRequest class, we’ll define a set of rules in the rules method to validate the new blog posts:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
public function authorize()
{
// Allow only logged-in users to create a blog post.
return auth()->check();
}
public function rules()
{
return [
'title' => 'required|max:255|unique:posts',
'content' => 'required|min:100',
'image' => 'nullable|image|max:2048',
'tags' => 'array',
'tags.*' => 'exists:tags,id'
];
}
}Let’s break down these validation rules:
'title' => 'required|max:255|unique:posts'ensures that the title field is not empty, it does not exceed 255 characters, and it’s unique in thepoststable.'content' => 'required|min:100'checks that the content is present and is at least 100 characters long, ensuring meaningful blog posts.'image' => 'nullable|image|max:2048'allows an optional image upload, verifies that the file is indeed an image, and restricts its size to 2MB.'tags' => 'array'ensures that the tags input is an array, which is useful when selecting multiple tags for a post.'tags.*' => 'exists:tags,id'checks each item in the tags array to ensure it corresponds to an existing tag ID in thetagstable.
Using the Form Request in a Controller
Now that we’ve set up our StorePostRequest, we can use it in our PostController:
namespace App\Http\Controllers;
use App\Http\Requests\StorePostRequest;
use App\Models\Post;
class PostController extends Controller
{
// other methods
public function store(StorePostRequest $request)
{
// The validated data is automatically retrieved
$validatedData = $request->validated();
// Create and save the new post with the validated data
$post = Post::create($validatedData);
// Attach tags if provided
if ($request->has('tags')) {
$post->tags()->sync($request->tags);
}
// Redirect to the new post with a success message
return redirect()->route('posts.show', $post)
->with('success', 'Post created successfully!');
}
}Inline Validation vs Form Request Classes
Laravel gives you two ways to validate incoming data: directly in the controller with $request->validate(), or through a dedicated Form Request class. Both are valid — the right choice depends on your situation.
Inline validation with $request->validate()
Inline validation is the quickest approach and works well for simple endpoints that are only used in one place:
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|max:255',
'content' => 'required|min:100',
]);
Post::create($validated);
return redirect()->route('posts.index');
}If validation fails, Laravel automatically redirects back with the errors and old input. For API requests, it returns a 422 JSON response.
When to use a Form Request class
Use a Form Request class when:
The same validation logic is reused across multiple controller methods (e.g.,
storeandupdate).You need custom authorization logic alongside validation.
The rules are complex enough that keeping them in the controller makes the method hard to read.
You want custom error messages defined in one place using the
messages()method.
Custom Validation Rules
Laravel's built-in rules cover most cases, but sometimes you need to validate something specific to your application. You can generate a custom rule class with Artisan:
php artisan make:rule NoSpamWordsThis creates app/Rules/NoSpamWords.php. Implement the validate method to define the rule logic:
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class NoSpamWords implements ValidationRule
{
/**
* Run the validation rule.
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$spamWords = ['casino', 'free money', 'click here'];
foreach ($spamWords as $word) {
if (str_contains(strtolower($value), $word)) {
$fail("The :attribute contains a prohibited word: {$word}.");
return;
}
}
}
}Use the rule in your Form Request or inline validation by passing a new instance:
use App\Rules\NoSpamWords;
public function rules(): array
{
return [
'title' => ['required', 'max:255', new NoSpamWords],
'content' => ['required', 'min:100', new NoSpamWords],
];
}Conditional Validation
Sometimes a field should only be validated if it is present, or only under certain conditions. Laravel provides two useful rules for this.
The sometimes rule
The sometimes rule tells Laravel: "only validate this field if it is present in the request." This is useful for partial update forms:
public function rules(): array
{
return [
// Only validate password if the user actually sent one
'password' => 'sometimes|required|min:8|confirmed',
];
}The required_if rule
The required_if rule makes a field required only when another field has a specific value. For example, requiring a company name only when the user selects "business" as their account type:
public function rules(): array
{
return [
'account_type' => 'required|in:personal,business',
'company_name' => 'required_if:account_type,business|max:255',
];
}Related rules include required_unless, required_with, and required_without — all follow the same pattern of making a field conditionally required based on the presence or value of other fields.
Displaying Validation Errors in Blade
When validation fails, Laravel flashes errors to the session and redirects back to the form. In Blade templates, use the @error directive to show per-field error messages:
<div>
<label for="title">Title</label>
<input
id="title"
name="title"
type="text"
value="{{ old('title') }}"
class="{{ $errors->has('title') ? 'border-red-500' : '' }}"
>
@error('title')
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
@enderror
</div>Always pair error display with old('field') to restore the user's previously entered value so they do not have to retype the whole form after a validation failure.
To display the first error for a field programmatically (outside of a template directive), use:
// In a Blade template
{{ $errors->first('title') }}
// Check if any errors exist
@if ($errors->any())
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
Conclusion
Form requests and validation rules in Laravel work together to provide a robust system for handling user input. By using these tools, you can ensure that every blog post on your site meets your standards for quality and consistency. The rules help prevent common issues like duplicate titles or insufficient content, while the form requests keep your controller methods clean and focused on their core responsibilities.
Upcoming Articles in the Series
This article is part of our series Laravel for Beginners: A Step-by-Step Guide to Learn the Concepts.
Bring Your Ideas to Life 🚀
If you need help with a Laravel project let’s get in touch.
Lucky Media is proud to be recognized as a leading Laravel Development Agency
Frequently Asked Questions
When should I use a Form Request vs inline validation?
Use inline $request->validate() for simple, one-off rules that do not need to be reused. Use a Form Request class when the rules are complex, when the same rules apply to more than one controller method, or when you want to keep your controller lean. Form Requests also let you define custom error messages and authorization logic alongside validation in a single, testable class.
How do I create a custom validation rule in Laravel?
Run php artisan make:rule RuleName. This creates a class in app/Rules/ with a validate(string $attribute, mixed $value, Closure $fail) method. Call $fail() with an error message to signal that validation failed. Then pass new RuleName as an element in your rules array for any field that needs it.
How do I show validation errors in Blade?
Use the @error('field') directive in your Blade template. Between @error and @enderror, the $message variable contains the first error for that field. Always pair error display with old('field') on the input so users do not lose their entered values on redirect.
Can I validate arrays in Laravel?
Yes. Use the array rule to ensure the field is an array, then use dot-star notation to validate each element. For example, 'tags' => 'array' validates that tags is an array, and 'tags.*' => 'exists:tags,id' validates that every item in the array corresponds to a real tag ID. You can also validate nested arrays using deeper dot notation like 'items.*.quantity' => 'required|integer|min:1'.
Technologies

Stay up-to-date
Be updated with all news, products and tips we share!
On this page
- 2026 UPDATE - LARAVEL 13
- Preventing unauthorized entry to your site
- Creating a Form Request
- Inline Validation vs Form Request Classes
- Custom Validation Rules
- Conditional Validation
- Displaying Validation Errors in Blade
- Conclusion
- Upcoming Articles in the Series
- Bring Your Ideas to Life 🚀
- Frequently Asked Questions

