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

Supported Entry Points

The same rule-set inference applies to these statically resolvable calls.

Entry pointInferred return
Validator::make($data, $rules)->validated()Validated shape
Factory::make($data, $rules)->validated()Validated shape
Factory::validate($data, $rules)Validated shape
Validator::validate($data, $rules) facadeValidated shape
Request::validate($rules)Validated shape
Controller $this->validate($request, $rules)Validated shape
validator($data, $rules)->validated() helperValidated shape
$validator->setRules($rules)->validated()Replacement shape when the return is used
FormRequest::validated() / supported safe()Validated shape when FormRequest inference is enabled

Named data and rules arguments are supported. Dynamic rule sets retain Laravel’s broad declared return types. Calls that supply the relevant argument only through ... unpacking also retain those broad types rather than guessing which unpacked element contains the rules.

If the input does not match the rules, Laravel throws Illuminate\Validation\ValidationException. For successful input, the extension infers the values and shape Laravel may preserve.

A directly constructed Illuminate\Validation\Validator retains Laravel’s broad declared return type and is not narrowed from configuration assumptions such as includeUnvalidatedArrayKeys.

setRules()

Larastan provides its own stub for Illuminate\Validation\Validator, and PHPStan does not merge multiple stubs for the same class. When both extensions are installed, Larastan’s stub takes precedence, so an ignored setRules() return can leave the validator’s previously inferred rules in place. Chain the call or assign its return value:

$validator->setRules($rules)->validated();
$validator = $validator->setRules($rules);

Input refinement

A successful direct facade or Factory::validate() call can refine safe, statically resolvable top-level fields in the caller’s original array.

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

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

This is an input constraint, not a claim that the original array was replaced by validated() output. Unrelated input keys may still exist.

Refinement is limited to:

  • a simple input variable;
  • arguments whose evaluation is known not to mutate program state.

The following are not used to narrow the caller’s array:

  • nested and wildcard paths;
  • exclusion and missing rules;
  • rule sets containing custom or opaque runtime behavior.

Guaranteed fields are added. An optional field is narrowed only when the input’s existing type already proves that the field is present.

This post-call refinement assumes Laravel’s ordinary factory and validator execution. Application-defined replacements for that execution path can invalidate the inferred constraint.