confirmed

Requires a matching {field}_confirmation input, or a custom field named after the colon.

Signature
confirmed

Parameters

ParameterTypeDescription
$fieldoptionalstring= {field}_confirmationName of the confirmation input to compare against, written as `confirmed:repeat_username`. Omit it to use the default {field}_confirmation convention.

Errors

Nothing on its own; a failure surfaces as Illuminate\Validation\ValidationException when run through validate() or a form request.

Changelog

  • PHP 11.xAdded an optional parameter so a custom confirmation field name can be given, e.g. confirmed:repeat_username.

The field under validation must have a matching field of {field}_confirmation. If the field under validation is password, a matching password_confirmation field must be present in the input. You may also pass a custom confirmation field name — confirmed:repeat_username expects a repeat_username input to match.

The confirmation field needs no rules

Only the field carrying confirmed is validated, and only it appears in validated(). That is the point: you never accidentally pass password_confirmation to User::create(), because validated() returns only attributes that have rules attached.

It is not an implicit rule

This is the failure mode worth knowing. If password itself is missing or empty, confirmed never runs and validation passes — a form posting nothing at all sails through. Always write 'password' => ['required', 'confirmed'].

The comparison is strict on strings

Values are compared with a strict check, so "1" and 1 do not match. That rarely matters for passwords but bites when confirming a numeric field. Note also that TrimStrings runs first, so trailing whitespace differences never cause a mismatch on ordinary form input.

Example

Example · php
<?php

use Illuminate\Support\Facades\Validator;

$rules = ['password' => ['required', 'confirmed', 'min:8']];

$ok = Validator::make([
    'password'              => 'correct-horse',
    'password_confirmation' => 'correct-horse',
], $rules);

$bad = Validator::make([
    'password'              => 'correct-horse',
    'password_confirmation' => 'correct-hors',
], $rules);

var_dump($ok->passes());
var_dump($bad->passes());
print_r($ok->validated());
print_r($bad->errors()->all());

// bool(true)
// bool(false)
// Array
// (
//     [password] => correct-horse
// )
// Array
// (
//     [0] => The password field confirmation does not match.
// )

When to use it

  • Confirming a new password on a registration or password-reset form.
  • Asking users to retype an email address on a high-stakes signup.
  • Confirming a destructive value such as an account name before deletion.
  • Matching a camelCase front-end field with confirmed:passwordConfirmation.

Frequently asked questions

What field name does confirmed look for?

By default `{field}_confirmation` — so `password` pairs with `password_confirmation`. Since Laravel 11 you can name a different field by passing it as a parameter, as in `confirmed:repeat_username`.

Does password_confirmation appear in validated()?

No. `validated()` returns only attributes that have rules of their own, and the confirmation field has none. That is why the result of a registration form request can be passed directly to `User::create()` without stripping anything.

Why did my empty password form pass validation?

Because `confirmed` is not an implicit rule and is skipped when the field is absent or empty. Add `required` in front of it: `'password' => ['required', 'confirmed', 'min:8']`.

More examples

Why it must be paired with required

Like almost every rule other than `required` and its variants, `confirmed` does not run against an absent or empty attribute. A password-reset form guarded only by `confirmed|min:8` therefore accepts a completely empty POST.

Example · php
<?php

use Illuminate\Support\Facades\Validator;

$emptySubmission = [];

// confirmed alone: skipped entirely, so an empty form passes.
$loose  = Validator::make($emptySubmission, ['password' => 'confirmed|min:8']);

// With required: the missing field is caught.
$strict = Validator::make($emptySubmission, ['password' => 'required|confirmed|min:8']);

var_dump($loose->passes());
var_dump($strict->passes());
print_r($strict->errors()->all());

// bool(true)    <- nothing was submitted and nothing complained
// bool(false)
// Array
// (
//     [0] => The password field is required.
// )

A custom confirmation field name

Without the parameter, this rule would look for `password_confirmation` and fail against a front end that sends `passwordConfirmation`. Note that the confirmation key is absent from `validated()` either way, so the array can be handed straight to a password update.

Example · php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;

class ResetPasswordRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'token'    => ['required', 'string'],
            'email'    => ['required', 'email'],
            // The SPA posts camelCase, so name the field explicitly.
            'password' => [
                'required',
                'confirmed:passwordConfirmation',
                Password::defaults(),
            ],
        ];
    }
}

// print_r($request->validated());
//
// Array
// (
//     [token] => 9f2c...
//     [email] => [email protected]
//     [password] => correct-horse-battery
// )

confirmed compares strictly

The comparison is type-aware, so an integer sent by a JSON client will not match a string confirmation. In an ordinary HTML form both values arrive as strings and this never comes up; in a JSON API it is worth casting or validating both fields to the same type first.

Example · php
<?php

use Illuminate\Support\Facades\Validator;

$rules = ['pin' => ['required', 'confirmed']];

// Same characters, different PHP types.
$mixed = Validator::make(['pin' => 1234, 'pin_confirmation' => '1234'], $rules);

// Both strings.
$same  = Validator::make(['pin' => '1234', 'pin_confirmation' => '1234'], $rules);

var_dump($mixed->passes());
var_dump($same->passes());

// bool(false)
// bool(true)

Discussion

  • Be the first to comment on this lesson.