Reader Stacks

Laravel Form Validation: The Core Rules With Examples

required, min/max, email, and unique — the validation rules that cover most real forms, plus the Form Request pattern for keeping validation out of the controller.

Laravel's validator covers the large majority of real form-validation needs with a compact rule syntax — most forms only need a handful of these rules combined.

Inline validation in a controller

$validated = $request->validate([
    'name' => ['required', 'string', 'max:255'],
    'email' => ['required', 'email:rfc', 'unique:users,email'],
    'password' => ['required', 'min:8', 'confirmed'],
    'age' => ['nullable', 'integer', 'min:18'],
]);

The rules that cover most cases

  • required / nullable — whether the field must be present at all
  • string / integer / numeric / boolean — basic type checks
  • min: / max: — for strings, this is character length; for numbers, it's the value itself; for arrays, it's item count — the same rule name means different things depending on the field's other type rule
  • email:rfc — validates email format; the rfc variant is the standard choice, other variants exist for stricter DNS/mailbox checks
  • unique:table,column — checks the database for an existing value, essential for things like email or username fields
  • confirmed — expects a matching _confirmation field (e.g. password_confirmation) and fails if they don't match

Custom error messages

$request->validate([
    'email' => 'required|email',
], [
    'email.required' => 'Please enter your email address.',
    'email.email' => 'That doesn\'t look like a valid email.',
]);

Moving validation into a Form Request

For anything beyond a trivial form, a dedicated Form Request class keeps the controller focused on orchestration:

php artisan make:request StoreUserRequest
class StoreUserRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'unique:users,email'],
        ];
    }
}
public function store(StoreUserRequest $request)
{
    $validated = $request->validated();
}

Laravel automatically runs the Form Request's validation before the controller method executes — if it fails, the request never reaches your controller code at all, and the user is redirected back with errors.

nullable does not make a field optional in every sense

nullable tells subsequent rules that null is acceptable; it does not mean "ignore any invalid value if the field is present." If an optional age field contains abc, the integer rule still fails. Use sometimes when the rules should only run if a key is present at all, and combine it with nullable when both absence and explicit null are valid states.

Updating an existing row needs an explicit unique exception

A create rule such as unique:users,email rejects the current user's unchanged email during an update because that value already exists — on the row being edited. Use the fluent rule and ignore the trusted model instance:

use Illuminate\Validation\Rule;

'email' => [
    'required',
    'email',
    Rule::unique('users', 'email')->ignore($user),
],

Do not pass a request-controlled ID into ignore(); the exception should come from the model the application has already resolved and authorized.

Validation and authorization are separate gates

A Form Request has both authorize() and rules() because structurally valid input can still be forbidden for the current user. "This status value is one of the allowed strings" is validation; "this user may change an order to that status" is authorization. Keeping those decisions separate prevents a detailed rule set from being mistaken for an access-control layer.

Use validated data as an allow-list

After validation, prefer $request->validated() or $request->safe()->only(...) over passing $request->all() into a model. Validation then does double duty as a clear input contract: fields that were never approved by the rules do not quietly reach mass assignment.

Topics: Forms & Validation