PHPStan Levels 0–9 Explained
Also Known As
TL;DR
Explanation
PHPStan's analysis levels control strictness progressively. Level 0: basic checks (unknown classes, undefined variables). Level 1: possibly-undefined variables, unknown magic methods. Level 2: unknown methods on all expressions. Level 3: return type checking. Level 4: dead code detection (unreachable, always-true conditions). Level 5: type-checking method arguments. Level 6: missing typehints reported. Level 7: union type narrowing. Level 8: nullable types checked strictly. Level 9: mixed type treated as error — the strictest, requiring fully typed code. Practical approach: start at the current level your codebase passes, incrementally raise it, fix the reported issues, commit. Aim for level 6+ on greenfield projects; use phpstan-baseline.neon to suppress legacy errors while raising the level.
Common Misconception
Why It Matters
Common Mistakes
- Staying at level 0 or 1 because higher levels produce errors — the errors are real bugs worth fixing.
- Not using the baseline feature to start at level 8 on a legacy codebase — baseline lets you fix incrementally.
- Suppressing PHPStan errors with @phpstan-ignore without understanding what is being ignored.
- Not increasing the level over time — teams get comfortable at their current level and never progress.
Code Examples
# phpstan.neon — too permissive:
parameters:
level: 0 # Almost no checks — false sense of security
# Progressive baseline approach:
# 1. Run: vendor/bin/phpstan analyse --level=8 --generate-baseline
# 2. Set level: 8 in phpstan.neon
# 3. Fix new violations as they are introduced
# 4. Chip away at baseline errors over time
# phpstan.neon
parameters:
level: 6
paths:
- src
excludePaths:
- src/Legacy
# Level overview:
# 0 — basic checks (unknown classes, wrong arg count)
# 1 — undefined variables, unknown magic methods
# 2 — unknown methods, checks on all expression types
# 3 — return type checking
# 4 — dead code, always-true/false conditions
# 5 — method/property existence on mixed
# 6 — type strictness on method calls (recommended minimum)
# 7 — union type narrowing
# 8 — nullable strictness
# 9 — strict mode — all rules on
# max — same as 9 + bleeding edge rules
$ vendor/bin/phpstan analyse
# Generate baseline for existing code:
$ vendor/bin/phpstan analyse --generate-baseline