Supported Entry Points
The same rule-set inference applies to these statically resolvable calls.
| Entry point | Inferred 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) facade | Validated shape |
Request::validate($rules) | Validated shape |
Controller $this->validate($request, $rules) | Validated shape |
validator($data, $rules)->validated() helper | Validated 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.