The levels, explained
level: 5 in a phpstan.neon looks like a score. It isn't. It's a list of checks you've agreed to, and every level keeps all the checks below it and adds a few more. Knowing what each level adds is how you read a report and know what it's asking for.
What each level adds
| Level | Adds |
|---|---|
| 0 | The basics: unknown classes and functions, unknown methods called on $this, the wrong number of arguments, and variables that are never defined. |
| 1 | Variables that might not be defined, plus unknown magic methods and properties on classes with __call and __get. |
| 2 | Unknown methods and properties on every expression, not just $this. PHPDoc types are validated too. |
| 3 | Return types, and the types assigned to properties. |
| 4 | Dead code: checks that are always true or always false, and code that can never run. |
| 5 | The types of arguments passed to methods and functions. |
| 6 | Missing type declarations, including what's inside your arrays. |
| 7 | Types that are only maybe right: a union with one wrong member, or an int where only some ints will do. |
| 8 | Calling methods and reading properties on something that might be null. |
| 9 | Strict about explicit mixed: about the only thing you can do with it is pass it on to something else that accepts mixed. |
| 10 | Just as strict about implicit mixed, where a type is missing entirely. |
max always means the highest level the installed PHPStan has. Today that's 10.
The early levels catch code that would crash. The later ones catch code that might do the wrong thing. That's why a project can run perfectly well at level 2 and still produce hundreds of errors at level 6. Nothing new broke. You've just asked PHPStan to check things it was ignoring before.
The climb in this course
Every exercise shows its target level, and that target only goes up:
| World | Levels | What changes |
|---|---|---|
| 1 Strict Types | up to 5 | PHP's own types, checked by PHPStan as well as at runtime. |
| 2 Honest Types | 6 to 8 | Saying what's inside arrays, strings and generics. |
| 3 PHPStan to Max | 9, 10 and beyond | mixed, baselines, extensions, and strict rules. |
You'll move up one level at a time, so each new set of errors arrives with the lesson that explains it.
This level's exercise
Discount.php is clean at level 0. At level 3 it has three errors, and each one comes from a different level. Work out which level reports each error, then fix them. They're all real bugs, and the tests will show you.