{
    "slug": "phpstan_levels",
    "term": "PHPStan Levels 0–9 Explained",
    "category": "style",
    "difficulty": "intermediate",
    "short": "PHPStan's 10 strictness levels — from basic undefined variable checks (0) to full generic type inference and strict mixed handling (9).",
    "long": "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.",
    "aliases": [
        "PHPStan level",
        "PHPStan strictness",
        "PHPStan 0-9"
    ],
    "tags": [
        "style",
        "php",
        "static-analysis",
        "quality"
    ],
    "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."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "psalm_annotations",
        "php_cs_fixer",
        "type_declarations",
        "dead_code_detection"
    ],
    "prerequisites": [
        "static_analysis",
        "type_declarations",
        "strict_types"
    ],
    "refs": [
        "https://phpstan.org/user-guide/rule-levels"
    ],
    "bad_code": "# phpstan.neon — too permissive:\nparameters:\n    level: 0  # Almost no checks — false sense of security\n\n# Progressive baseline approach:\n# 1. Run: vendor/bin/phpstan analyse --level=8 --generate-baseline\n# 2. Set level: 8 in phpstan.neon\n# 3. Fix new violations as they are introduced\n# 4. Chip away at baseline errors over time",
    "good_code": "# phpstan.neon\nparameters:\n    level: 6\n    paths:\n        - src\n    excludePaths:\n        - src/Legacy\n\n# Level overview:\n# 0 — basic checks (unknown classes, wrong arg count)\n# 1 — undefined variables, unknown magic methods\n# 2 — unknown methods, checks on all expression types\n# 3 — return type checking\n# 4 — dead code, always-true/false conditions\n# 5 — method/property existence on mixed\n# 6 — type strictness on method calls (recommended minimum)\n# 7 — union type narrowing\n# 8 — nullable strictness\n# 9 — strict mode — all rules on\n# max — same as 9 + bleeding edge rules\n\n$ vendor/bin/phpstan analyse\n# Generate baseline for existing code:\n$ vendor/bin/phpstan analyse --generate-baseline",
    "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",
    "severity": "medium",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/phpstan_levels",
        "html_url": "https://codeclaritylab.com/glossary/phpstan_levels",
        "json_url": "https://codeclaritylab.com/glossary/phpstan_levels.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[PHPStan Levels 0–9 Explained](https://codeclaritylab.com/glossary/phpstan_levels) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/phpstan_levels"
            }
        }
    }
}