Formatting, static analysis, and tests answer different questions. A formatter makes code mechanically consistent, PHPStan reasons about types and control flow without running the application, and tests execute selected behavior against examples and boundaries.
After this lesson, you can install a static analyzer as a development dependency, run it against owned source paths, raise strictness gradually, and combine lint, style, analysis, and tests into one repeatable project command.
| Check | Finds | Does Not Prove |
|---|---|---|
| php -l | Parse errors | Correct behavior |
| Formatter or PHPCS | Style differences | Type safety |
| PHPStan | Type and flow inconsistencies | Database or HTTP behavior |
| PHPUnit | Executed assertions | Every untested path |
PSR-12 provides shared formatting expectations that reduce review noise between projects. Enforce style with a tool rather than spending review time on spaces and braces. Keep generated files and vendor dependencies outside the project style target.
Install development tools through Composer so the lock file pins the team version. Analyze application source and tests, not vendor code.
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse src tests --level=6
Use vendor\bin\phpstan on Windows Command Prompt when forward-slash invocation is unavailable.
Native types describe runtime contracts; PHPDoc can refine collection shapes and generics for analysis. Prefer changing vague application design over adding a broad ignore rule.
<?php
/** @param list<array{id:int, title:string}> $tasks */
function taskTitles(array $tasks): array
{
return array_map(
static fn (array $task): string => $task['title'],
$tasks,
);
}
The shape lets analysis detect a missing title key or an unexpected value type before that path executes.
A baseline can record existing findings during gradual adoption, but new code should not add new ignored failures. Every direct suppression should name a narrow tool identifier and include a reason the team can remove later.
Expose the local checks as Composer scripts and run the same command in continuous integration. Fail early on syntax, then style, static analysis, unit tests, and boundary tests.
{
"scripts": {
"analyse": "phpstan analyse src tests --level=6",
"test": "phpunit",
"quality": ["@analyse", "@test"]
}
}
0 of 2 checked
Try this next
0 of 2 completed
Explore 500+ free tutorials across 20+ languages and frameworks.