Laravel Validation Rules Reference Guide

A Laravel validation rules reference guide for validating request data with rules, custom messages, and Form Requests.

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

RuleChecks
requiredPresent and not empty.
nullableAllows the field to be missing or null — skips other rules when it is.
sometimesOnly validates the field when it's actually present in the input.
string / integer / numeric / boolean / arrayMust be that PHP type.
emailMust be a validly formatted email address (RFC-compliant by default — doesn't confirm the mailbox actually exists, see below).
unique:users,emailNo existing row in users.email matches this value.
exists:users,idA row with this value must already exist in users.id.
min:8 / max:255Minimum/maximum length (strings), value (numbers), or item count (arrays).
between:1,100Value or length falls within the given range.
confirmedA 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-dMust be a valid date, optionally in a specific format.
in:draft,published,archivedValue 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,pdfUploaded file constraints, including allowed MIME types.
required_if:type,businessRequired only when another field has a given value.
same:password / different:old_passwordMust (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'],
ValidatorChecks
rfcRFC 5322 format — the default, and the only one applied if you just write email on its own.
strictRFC 5322 with no tolerance for the deprecated quirks (e.g. trailing dots) the plain rfc check allows.
dnsThe domain must have a valid MX record — catches typos and made-up domains, but adds a real DNS lookup to each request.
spoofRejects homograph/spoofing characters (e.g. Cyrillic look-alikes) used to impersonate another address.
filterValidates using PHP's filter_var(FILTER_VALIDATE_EMAIL) instead of the RFC parser — looser in some edge cases.
filter_unicodeSame 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();
}