php 89 lines · 3 tabs

Laravel Form Request Validation for Signup With Custom Rules and Error Responses

Shared by codesnips Jul 2026
3 tabs
<?php

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Validation\Rules\Password;

class RegisterUserRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    protected function prepareForValidation(): void
    {
        $this->merge([
            'email' => strtolower(trim((string) $this->input('email'))),
            'name' => trim((string) $this->input('name')),
        ]);
    }

    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email:rfc', 'max:255', 'unique:users,email'],
            'password' => [
                'required',
                'confirmed',
                Password::min(10)->mixedCase()->numbers()->symbols(),
            ],
        ];
    }

    public function messages(): array
    {
        return [
            'email.unique' => 'An account with that email already exists.',
            'password.confirmed' => 'The password confirmation does not match.',
        ];
    }

    protected function failedValidation(Validator $validator): void
    {
        throw new HttpResponseException(response()->json([
            'message' => 'The given data was invalid.',
            'errors' => $validator->errors(),
        ], 422));
    }
}
3 files · php Explain with highlit

This snippet shows how Laravel's Form Request classes centralize input validation for a signup flow, keeping controllers thin while still returning consistent error payloads to both web and API clients. The core idea is that validation, authorization, and normalization all live in a dedicated request object that runs before the controller action executes.

In RegisterUserRequest, the authorize method returns true because signup is public — but this hook exists so protected endpoints can gate access before any validation runs. The rules method declares the constraints: email must be a valid RFC address that is unique against the users table, and password uses the Password rule builder to require a minimum length, mixed case, and at least one symbol. Using confirmed on the password automatically checks for a matching password_confirmation field, which avoids hand-written comparison logic. The messages method overrides a few defaults so the errors read like product copy rather than framework jargon.

A subtle but important piece is prepareForValidation, which runs before the rules are applied. It lowercases and trims the email so uniqueness checks and later lookups behave predictably — normalizing input at the boundary prevents duplicate accounts that differ only by casing or stray whitespace. The failedValidation override is what makes this work cleanly for JSON APIs: instead of Laravel's default redirect-with-session-errors behavior, it throws an HttpResponseException carrying a structured 422 body, so front-end clients always receive machine-readable errors under an errors key.

In RegisteredUserController, the action type-hints RegisterUserRequest. Laravel resolves and runs the request through the service container, so by the time store executes, the data is guaranteed valid — $request->validated() returns only the whitelisted, sanitized fields. This is safer than pulling raw input because it prevents mass-assignment of unexpected keys. The password is hashed with Hash::make before persistence, and a 201 response is returned with the created resource.

The trade-off is indirection: logic moves out of the controller into a class that must be discovered. In exchange, validation becomes reusable, testable in isolation, and consistent across every entry point that reuses the request. Reach for this pattern whenever an endpoint accepts non-trivial user input.


Related snips

Share this code

Here's the card — post it anywhere.

Laravel Form Request Validation for Signup With Custom Rules and Error Responses — share card
Link copied