← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

PHPStan Levels 0–9 Explained

Style PHP 7.1+ Intermediate
debt(d3/e3/b3/t5)
d3 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'default linter catches the common case' (d3), since PHPStan itself is the detection tool — running phpstan with any configured level immediately surfaces whether the project is under-leveraged, and the absence of phpstan.neon is trivially visible in CI.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3), per quick_fix: configure phpstan.neon, create a baseline, and raise the level incrementally. It's a config change plus iterative cleanup within one tool's scope, not a cross-file refactor.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3), since the level choice applies across all PHP contexts (web/cli/queue) and shapes ongoing typing discipline, but it lives in a single config file and can be adjusted without architectural rework.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap most devs eventually learn' (t5), matching the misconception that level 9 should be the immediate target — newcomers reasonably assume 'highest = best' but the documented practice is to start low and ratchet up with a baseline.

About DEBT scoring →

Also Known As

PHPStan level PHPStan strictness PHPStan 0-9

TL;DR

PHPStan's 10 strictness levels — from basic undefined variable checks (0) to full generic type inference and strict mixed handling (9).

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

PHPStan level 9 should be the immediate target for any project. Start at the level that passes on your current codebase and raise it incrementally — attempting level 9 on a large legacy codebase produces thousands of errors that overwhelm the team and discourage adoption entirely.

Why It Matters

PHPStan's levels 0-9 progressively enable stricter checks — starting at 0 gives little value; level 8+ catches real type errors that cause production bugs.

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

✗ Vulnerable
# 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
✓ Fixed
# 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

Added 15 Mar 2026
Edited 22 Mar 2026
Views 81
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 2 pings M 0 pings T 2 pings W 1 ping T 2 pings F 4 pings S 8 pings S 7 pings M 1 ping T 0 pings W 0 pings T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W
No pings yet today
PetalBot 1
Scrapy 23 Perplexity 10 Amazonbot 6 SEMrush 5 Google 4 Ahrefs 4 ChatGPT 4 Unknown AI 3 Claude 2 Bing 1 Meta AI 1 PetalBot 1
crawler 59 crawler_json 4 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Start at level 0 on existing code, create a baseline to ignore existing errors, then gradually raise the level — target level 6 for new projects
📦 Applies To
PHP 7.1+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
No phpstan.neon config; running at level 0 with hundreds of suppressed errors; no baseline file
Auto-detectable: ✓ Yes phpstan psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: File


✓ schema.org compliant