Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Understanding Inferred Types

The extension describes what Laravel can return after successful validation. It does not describe the type a rule name appears to promise.

Soundness

Every successful Laravel output must be a subtype of the inferred type. When Laravel preserves several native representations, the inferred type is a union of those representations.

$validated = Validator::make($input, [
    'age' => 'required|integer',
])->validated();

\PHPStan\dumpType($validated);
// array{age: float|int|numeric-string|Stringable|true}

integer accepts and preserves 1, 1.0, true, numeric strings, and compatible Stringable objects. Narrowing that to int would be false. See Laravel Validation and Type Safety and Validation Rules.

Add an adjacent native-family rule when you know the input representation:

$validated = Validator::make($input, [
    'age' => 'required|integer|string',
])->validated();

\PHPStan\dumpType($validated);
// array{age: numeric-string}

Presence is separate from the value type

required makes a key required. It does not change the value family. present requires the key and still allows a blank string to bypass non-implicit adjacent rules. missing and exclude omit the path from successful output.

Details are in Presence and Output Projection.

Nested arrays and wildcards

An explicit parent array rule makes that offset required. Wildcard children alone do not: the parent may be absent, and when present it is still a non-null array.

$validated = Validator::make($input, [
    'person' => 'required|array',
    'person.*.email' => 'required|string|email',
])->validated();

\PHPStan\dumpType($validated);
// array{person: array<int|string, array{email: non-empty-string}>}

Without 'person' => 'required|array', the parent is person?.

Bare array parents with nested children are rebuilt from those children. Parameterized array:name,email and array_keys preserve the permitted parent instead. See Presence and Output Projection.

When inference stays conservative

Precise inference requires a complete, statically visible rule expression. Assigned builders, dynamic calls, callbacks, macros, and unknown custom predicates fall back rather than guessing. The common rule is in Static Resolvability.

Input refinement after validate()

A successful direct facade or Factory::validate() call can narrow safe top-level fields on the caller’s original array. That is an input constraint, not a claim that the array was replaced by validated() output.

/** @var array<string, mixed> $input */
Validator::validate($input, ['name' => 'required|string']);

\PHPStan\dumpType($input['name']); // string

Limits are listed under Supported Entry Points.