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:

  1. Developer pushes code.

  2. CI server automatically runs PHPStan or Psalm.

  3. Errors are reported.

  4. Build fails if serious issues exist.

  5. 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.