PHPStan & Psalm — Static Analysis as a First-Class Citizen
Run PHPStan at its strictest level on a modern PHP codebase and you get TypeScript-grade type safety — with zero runtime overhead and no transpile step. This is one of the most important things PHP developers don't know they have.
# Install
composer require --dev phpstan/phpstan
# Run at max strictness (level 9)
vendor/bin/phpstan analyse src --level=9
At level 9, PHPStan catches bugs that would otherwise only surface at runtime:
// PHPStan catches this at analysis time, not in production:
function processUser(?User $user): string
{
return strtoupper($user->name);
// ^^^^^^^^^^^^
// Error: Cannot access property $name on null.
// Add a null check or change the type to User.
}
// After fix — PHPStan is satisfied:
function processUser(?User $user): string
{
if ($user === null) {
return 'Guest';
}
return strtoupper($user->name);
}
At higher levels, PHPStan enforces return types, detects dead code, validates array shapes, and understands generics via PHPDoc. Psalm (the alternative from Vimeo) goes even further with its type inference engine and taint analysis for security vulnerabilities.
# phpstan.neon — project configuration
parameters:
level: 9
paths:
- src
strictRules:
disallowedBacktick: true
disallowedConstructs:
- 'empty' # empty() masks bugs; be explicit
Significance: Confidence Without Ceremony
Static analysis turns PHP's optional type system into a mandatory one — without changing the language. A codebase with PHPStan at level 9 has fewer runtime surprises than many statically-typed languages, because the analyser understands nullability, generics, and control flow in ways that simple type declarations can't express.