Laravel Reference
Validating in a controller
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'age' => 'nullable|integer|min:18',
]);
Post::create($validated);
}
If validation fails, Laravel automatically redirects back with the errors flashed to the session (for a web request) or returns a 422 JSON response with the error details (for an API request) — nothing else to write.
Common rules
| Rule | Checks |
|---|---|
required | Present and not empty. |
nullable | Allows the field to be missing or null — skips other rules when it is. |
sometimes | Only validates the field when it's actually present in the input. |
string / integer / numeric / boolean / array | Must be that PHP type. |
email | Must be a validly formatted email address (RFC-compliant by default — doesn't confirm the mailbox actually exists, see below). |
unique:users,email | No existing row in users.email matches this value. |
exists:users,id | A row with this value must already exist in users.id. |
min:8 / max:255 | Minimum/maximum length (strings), value (numbers), or item count (arrays). |
between:1,100 | Value or length falls within the given range. |
confirmed | A matching {field}_confirmation field must be present (e.g. password confirmation — see the password checker or generator for testing what you're asking users to confirm). |
date / date_format:Y-m-d | Must be a valid date, optionally in a specific format. |
in:draft,published,archived | Value must be one of the given options. |
regex:/^[A-Z]+$/ | Must match the given regular expression (try one out in the regex tester first). |
file / image / mimes:jpg,png,pdf | Uploaded file constraints, including allowed MIME types. |
required_if:type,business | Required only when another field has a given value. |
same:password / different:old_password | Must (or must not) match another field's value. |
Stricter email checks
The plain email rule only checks the format is RFC-valid — it will happily accept foo@bar.qqzzxx, a domain that can never receive mail. Stack extra validators after a colon to tighten that up:
'email' => ['required', 'email:rfc,dns,spoof'],
| Validator | Checks |
|---|---|
rfc | RFC 5322 format — the default, and the only one applied if you just write email on its own. |
strict | RFC 5322 with no tolerance for the deprecated quirks (e.g. trailing dots) the plain rfc check allows. |
dns | The domain must have a valid MX record — catches typos and made-up domains, but adds a real DNS lookup to each request. |
spoof | Rejects homograph/spoofing characters (e.g. Cyrillic look-alikes) used to impersonate another address. |
filter | Validates using PHP's filter_var(FILTER_VALIDATE_EMAIL) instead of the RFC parser — looser in some edge cases. |
filter_unicode | Same as filter, but allows unicode characters in the address. |
Combine as many as you need, e.g. email:rfc,dns,spoof. Reach for dns on things like registration or contact forms where you actually want to know mail can be delivered — skip it on high-frequency paths (like a login lookup) since it adds a network round trip per request, and no combination proves a mailbox is actually monitored — only a verification email confirms that.
Custom error messages
$request->validate([
'title' => 'required|max:255',
], [
'title.required' => 'Please give your post a title.',
'title.max' => 'Titles cannot be longer than 255 characters.',
]);
Form Requests
For anything beyond a couple of rules, move validation into its own class so the controller stays focused on the actual logic.
php artisan make:request StorePostRequest
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
];
}
public function messages(): array
{
return [
'title.required' => 'Please give your post a title.',
];
}
}
public function store(StorePostRequest $request)
{
// Already validated by the time this method runs
Post::create($request->validated());
}
The authorize() stub above always returns true — see the policies and gates guide for using it to check whether the user is actually allowed to perform the request.
Manual validator instances
Useful outside of a controller/request, e.g. validating an array in a job or console command.
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($data, [
'email' => 'required|email',
]);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput();
}