Built-in validation rules such as required, email, or max are not enough for most real-word applications. Your requirements might need custom business logic such as checking if a username contains a certain word, or if a user has a specific role.
Laravel gives you three main ways to define custom validation:
Closure-Based Custom Rules (Inline in Controller)
This is the simplest way to define a custom rule using a closure (anonymous function) directly in your validation array.
Example: Disallow usernames containing “admin”
PHP:
$request->validate([ 'username' => [ 'required', function ($attribute, $value, $fail) { if (stripos($value, 'admin') !== false) { $fail('The username cannot contain the word "admin".'); } }, ],
]);
When to use: Small, one-time rules specific to a form.
Custom Rule Class (Reusable Rules)
Use Laravel’s artisan command to create a custom rule class.
Step 1: Create the rule
Bash:
php artisan make:rule Uppercase
Step 2: Define logic in the rule class
PHP:
// app/Rules/Uppercase.php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Uppercase implements Rule
{ public function passes($attribute, $value) { return strtoupper($value) === $value; } public function message() { return 'The :attribute must be in uppercase.'; }
}
Step 3: Use the rule in a controller
PHP:
use App\Rules\Uppercase;
$request->validate([ 'title' => ['required', new Uppercase],
]);
When to use: When the rule will be reused across different forms or logic is too complex for closures.
Extending the Validator (Custom Rule Name)
You can register your own validation rule globally using Laravel’s Validator::extend method (typically in a service provider).
Step 1: Extend Validator
PHP:
use Illuminate\Support\Facades\Validator;
public function boot()
{ Validator::extend('foo', function ($attribute, $value, $parameters, $validator) { return $value === 'foo'; });
}
Step 2: Use the new rule name
PHP:
$request->validate([ 'code' => 'required|foo',
]);
Optional: Custom message
PHP:
// resources/lang/en/validation.php
'foo' => 'The :attribute must be "foo".',
When to use: When you want clean, named rules you can apply like built-in rules.
Customizing Error Messages (All Methods)
You can customize error messages like this:
PHP:
$request->validate([ 'username' => 'required|min:5',
], [ 'username.required' => 'Please enter your username.', 'username.min' => 'Your username must be at least :min characters long.',
]);
This helps you keep messages user-friendly and in plain language.
Example Use Case: Validating Age Must Be Over 18
Custom Rule Class
Bash:
php artisan make:rule AgeOver18
Rule Logic
PHP:
public function passes($attribute, $value)
{ return Carbon\Carbon::parse($value)->age >= 18;
}
public function message()
{ return 'You must be at least 18 years old.';
}
Usage
PHP:
$request->validate([ 'dob' => ['required', 'date', new AgeOver18],
]);
Summary Table
Method | Use When | Reusability | Complexity |
Closure-based | Quick one-off logic | No | Simple |
Custom Rule Class | Rule used in multiple places | Yes | Medium |
Validator Extension | Want named rules | Yes | Advanced |
Pro Tips
- Group multiple custom rules in one file for better organization.
- Reuse custom rule classes to follow DRY principles.
- Store messages in resources/lang for localization support.