Human sense of Smell - PHPStan and Psalm for Static Code Analysis in PHP
Static code analysis is the process of examining PHP source code without actually executing it. Unlike testing, which runs the program to verify its behavior, static analysis inspects the code to identify potential errors, coding standard violations, type inconsistencies, dead code, and security issues before the application is deployed. Two of the most widely used static analysis tools in the PHP ecosystem are PHPStan and Psalm. These tools help developers improve code quality, reduce bugs, and maintain large codebases efficiently.
What is Static Code Analysis?
Static code analysis evaluates source code by checking its syntax, structure, data types, and programming logic. It identifies issues that may not be immediately visible during development but could lead to runtime errors. Since the code is not executed during analysis, developers can detect many problems early in the software development lifecycle.
Static analysis is commonly used for:
-
Detecting undefined variables and methods
-
Identifying incorrect parameter types
-
Finding unreachable or unused code
-
Verifying return types
-
Enforcing coding standards
-
Improving maintainability
-
Detecting potential bugs before deployment
Introduction to PHPStan
PHPStan (PHP Static Analysis Tool) is a static analyzer that focuses on finding bugs in PHP code by checking type safety and program logic. It understands modern PHP features and allows developers to analyze projects with varying levels of strictness.
PHPStan analyzes code without requiring the application to run. It reads class definitions, method signatures, variable assignments, and type declarations to determine whether the code is logically correct.
Features of PHPStan
-
Detects undefined variables and methods
-
Checks incorrect method calls
-
Verifies function arguments
-
Validates return types
-
Supports PHPDoc annotations
-
Understands namespaces and autoloading
-
Configurable analysis levels
-
Supports extensions for popular frameworks
Installing PHPStan
PHPStan is commonly installed using Composer.
composer require --dev phpstan/phpstan
To analyze a project:
vendor/bin/phpstan analyse
To analyze a specific directory:
vendor/bin/phpstan analyse app
Analysis Levels in PHPStan
PHPStan provides multiple analysis levels ranging from 0 to 9.
-
Level 0 checks only basic errors.
-
Higher levels enforce stricter type checking.
-
Level 9 provides the most comprehensive analysis.
Example:
vendor/bin/phpstan analyse --level=8 app
Choosing higher levels encourages developers to write cleaner and more reliable code.
PHPStan Configuration
A configuration file named phpstan.neon is used to customize analysis.
Example:
parameters:
level: 8
paths:
- app
- src
Additional settings can include ignored errors, custom extensions, bootstrap files, and memory limits.
Common Errors Detected by PHPStan
Undefined Variable
echo $name;
PHPStan reports that $name may not be defined.
Incorrect Return Type
function square(int $n): int
{
return "25";
}
PHPStan reports that a string is returned instead of an integer.
Invalid Method Call
$user->display();
If the display() method does not exist, PHPStan immediately reports the error.
Introduction to Psalm
Psalm is another advanced static analysis tool designed to detect programming mistakes and improve code quality. Like PHPStan, it performs deep inspection of PHP source code without executing it.
Psalm places strong emphasis on precise type inference and security analysis. It is particularly useful for large enterprise applications where strict type safety is important.
Features of Psalm
-
Advanced type checking
-
Automatic type inference
-
Detection of unreachable code
-
Security issue identification
-
Generic type support
-
Taint analysis
-
Plugin architecture
-
Framework integration
Installing Psalm
Install Psalm using Composer.
composer require --dev vimeo/psalm
Initialize Psalm:
vendor/bin/psalm --init
Run analysis:
vendor/bin/psalm
Psalm generates a detailed report describing detected problems and possible solutions.
Example of Type Checking
function add(int $a, int $b): int
{
return $a + $b;
}
echo add("5", 10);
Psalm reports that a string is passed where an integer is expected.
Type Inference
One of Psalm's strongest features is automatic type inference.
Example:
$value = 100;
Psalm automatically determines that $value is an integer.
Later, if the variable is assigned a different incompatible type:
$value = "Hello";
Psalm can warn about inconsistent type usage depending on project settings.
PHPDoc Support
Both PHPStan and Psalm understand PHPDoc annotations.
Example:
/**
* @param string $name
* @return string
*/
function greet($name)
{
return "Hello ".$name;
}
The analyzers use these annotations when native type declarations are unavailable.
Detecting Dead Code
Static analysis tools identify functions or variables that are never used.
Example:
function test()
{
echo "Unused";
}
If test() is never called, the analyzer may report it as unused code.
Removing unused code makes applications easier to maintain.
Generic Types
Psalm provides excellent support for generic collections.
Example:
/**
* @var array<int>
*/
$numbers = [10,20,30];
The analyzer understands that the array contains only integers.
If a string is inserted later:
$numbers[] = "Hello";
Psalm reports a type mismatch.
Security Analysis
Psalm includes taint analysis that helps detect security vulnerabilities.
Examples include:
-
SQL Injection
-
Cross-Site Scripting (XSS)
-
Command Injection
-
Unsafe user input handling
This feature allows developers to identify unsafe data flow before deployment.
Continuous Integration
Static analysis tools are commonly integrated into Continuous Integration (CI) pipelines.
Typical workflow:
-
Developer pushes code.
-
CI server automatically runs PHPStan or Psalm.
-
Errors are reported.
-
Build fails if serious issues exist.
-
Developer fixes problems before merging.
This process prevents defective code from reaching production.
Comparison Between PHPStan and Psalm
| Feature | PHPStan | Psalm |
|---|---|---|
| Ease of setup | Very easy | Easy |
| Type checking | Excellent | Excellent |
| Type inference | Strong | Very strong |
| Security analysis | Limited | Advanced |
| Generic support | Good | Excellent |
| Plugin ecosystem | Extensive | Extensive |
| Performance | Fast | Fast |
| Learning curve | Moderate | Moderate to Advanced |
Benefits of Using Static Analysis
-
Detects bugs before execution
-
Improves code quality
-
Encourages type-safe programming
-
Simplifies maintenance
-
Reduces debugging time
-
Enhances team collaboration
-
Supports refactoring with confidence
-
Improves software reliability
-
Detects hidden logical errors
-
Integrates easily with modern development workflows
Best Practices
-
Run static analysis regularly during development.
-
Gradually increase the analysis level as code quality improves.
-
Use native PHP type declarations wherever possible.
-
Add accurate PHPDoc annotations when needed.
-
Integrate PHPStan or Psalm into automated CI/CD pipelines.
-
Address reported issues promptly instead of suppressing them unnecessarily.
-
Keep the analysis tool and its configuration up to date with the latest PHP version.
-
Combine static analysis with unit testing for comprehensive quality assurance.
Conclusion
PHPStan and Psalm are powerful static code analysis tools that help developers identify programming errors before PHP applications are executed. They improve code quality by enforcing type safety, detecting logical mistakes, identifying unused code, and supporting modern PHP development practices. While PHPStan is known for its simplicity and configurable strictness, Psalm offers advanced type inference and security-focused analysis. Incorporating either or both tools into the development workflow leads to more reliable, maintainable, and secure PHP applications.