A missing type declaration in a service constructor, a tainted $_GET parameter flowing straight into a query string, a class upgraded to PHP 8.4 with deprecated call-by-reference semantics still lurking three levels down — these are the bugs that survive code review and land in production PHP applications. PHP code analysis catches them before the code ships. This guide covers every major tool in the 2026 PHP ecosystem — PHPStan, Psalm, PHPCS, Rector, and four more — and shows you how to layer them into a workflow that finds real bugs without drowning your team in noise. If you work in other languages, the same layering principles apply to Python static code analysis and Java static analysis.

What Is PHP Code Analysis?

PHP Code Analysis Pipeline .php Source Code class Foo Lexer Tokenizer T_CLASS T_STRING T_LBRACE AST Syntax Tree ClassNode MethodNode ExprNode Rule Engine type rules style rules sec rules Report Findings 3 errors 12 warnings 0 security Input tokens tree rules warnings count 1 2 3 4 5 No code is executed — analysis is fully static and safe to run on partial or incomplete files
The five-stage PHP static analysis pipeline. No runtime is involved at any point — the rule engine operates on the AST produced by the lexer and parser.

PHP code analysis is the automated inspection of PHP source files without executing them — a practice known formally as static program analysis. A PHP analyzer reads your .php files, constructs an abstract syntax tree (AST) from the parsed tokens, and then applies a configurable rule set to that tree. Findings — type mismatches, undefined variables, unreachable code, coding-standard violations, security sinks — are reported back to the developer in the terminal or CI pipeline, without a web server, database, or runtime being involved at any point.

The term is an umbrella over several distinct analysis categories, each requiring different tooling:

  • Type analysis — verifying that method arguments, return types, and property assignments are consistent with declared type annotations and inferred types. Handled by PHPStan and Psalm.
  • Coding standards enforcement — checking PSR-12 formatting, brace placement, naming conventions, and project-specific style rules. Handled by PHP_CodeSniffer (PHPCS).
  • Auto-formatting — deterministically rewriting code to match a defined style, eliminating style debates in reviews. Handled by PHP-CS-Fixer.
  • Automated refactoring — rewriting code to use newer language features or upgrade framework APIs. Handled by Rector.
  • Heuristic checks — cyclomatic complexity, dead code, overly long methods, naming conventions. Handled by PHPMD.
  • Taint analysis (SAST) — tracking user-supplied data from HTTP input through the call graph to dangerous sinks (database queries, HTML output, file writes). Handled by Psalm with taint mode and tools covered in our SAST tools guide.

Because none of these tools execute your application, they are safe to run on partially written code, fast enough for pre-commit hooks, and trivially embeddable in GitHub Actions — forming the static layer of a complete code quality pipeline. The human-review layer that sits on top of static analysis is covered in our guide to source code review tools.

Why PHP Static Analysis Matters in 2026

PHP's permissive dynamic typing has historically made entire categories of bugs invisible until runtime. The language has evolved dramatically — PHP 8.4 brings property hooks, asymmetric visibility, and a strengthened type system — but legacy codebases running PHP 7.x still exist in production, and even modern PHP applications can hide type-level bugs that no amount of unit testing will surface if the test suite does not cover every code path. Three trends make 2026 the right time to invest in a proper PHP code analysis stack:

  1. Type coverage is now practical. PHPStan and Psalm both support generics, conditional return types, template annotations, and PHP 8.x union types. A codebase with reasonable docblock coverage can run PHPStan at level 6 or higher and catch entire classes of null-dereference and argument-type bugs that no linter or test suite can see.
  2. Automated upgrades are real. Rector can rewrite a PHP 7.4 codebase to PHP 8.4 automatically — replacing deprecated constructs, adding union types, converting create_function calls, and updating framework API calls. What previously required weeks of manual migration now takes hours, with a static analysis pass afterward to verify correctness.
  3. Security shift-left is expected. PHP applications remain high-value targets for SQL injection and XSS. Running Psalm with taint analysis pre-merge catches tainted-data flows that no linter detects. For teams treating security as a first-class concern, the full static code analysis stack is now a minimum bar, not a nice-to-have.

The 8 Best PHP Code Analysis Tools

1. PHPStan — The Modern Default

PHPStan Strictness Levels: 0 → 10 strictness Level 0 Basic unknown class / method checks permissive Level 1 Possibly undefined variables Level 2 Unknown method return types Level 3 Return type checks on called methods Level 4 Dead code, basic type inference Level 5 Type inference · argument type checks ★ type inference Level 6 Check passed argument types strictly ← recommended Level 7 Report missing typehints Level 8 Null safety · nullable type propagation ★ null safety Level 9 Strict mixed type checks Level 10 Mixed strict · no implicit any type ★ mixed strict Start at level 0, incrementally raise — each level adds new checks without breaking the previous baseline
PHPStan's 11-level strictness ladder. Level 6 is the recommended starting point for production codebases; level 8 enables null-safety checks; level 10 enforces strict mixed types.

PHPStan is the most widely adopted PHP code analysis tool in 2026, and for good reason. Its defining feature is an eleven-level strictness ladder (0 through 10, with 0 being the most permissive and 10 the most strict) that lets teams adopt type analysis incrementally. A legacy codebase can start at level 0 with zero findings, progressively tighten the level over successive sprints, and eventually reach level 6 or higher — where genuine type-safety bugs surface — without being paralyzed by thousands of pre-existing issues on day one.

PHPStan performs bleeding-edge type inference: it understands generics via PHPDoc annotations, conditional return types, intersection types, and PHP 8.4 property hooks. It ships with a growing plugin ecosystem — most notably Larastan, the Laravel-specific extension that teaches PHPStan about Eloquent magic methods, relationship return types, and Blade templates. There are equivalent extensions for Symfony (phpstan-symfony) and Doctrine (phpstan-doctrine). Maintained by Ondrej Mirtes under MIT license.

composer require --dev phpstan/phpstan
# Run at level 6 on your src directory
./vendor/bin/phpstan analyse src/ --level=6
<?php
// PHPStan level 6 catches this at analysis time:
class OrderService {
    public function getTotal(Order $order): float {
        // Error: Property Order::$items might not be defined.
        return array_sum($order->items);
    }
}

2. Psalm — Vimeo's Security-First Analyzer

Psalm was developed by Vimeo and is the only major PHP analyzer with built-in taint analysis — the ability to track user-controlled data from its source (HTTP request parameters, cookies, file uploads) through the call graph to dangerous sinks (database queries, HTML output, system calls). This makes Psalm uniquely valuable for security-conscious teams: it can detect SQL injection and XSS vulnerabilities that PHPStan's type-only analysis completely misses.

Beyond security, Psalm offers granular @psalm-* annotation support — @psalm-pure, @psalm-immutable, @psalm-template — that lets teams encode rich invariants directly in docblocks. Psalm is slower than PHPStan on large codebases, but its error-level system (1 through 8) provides a comparable incremental adoption path. Maintained by the open-source community under MIT license.

composer require --dev vimeo/psalm
./vendor/bin/psalm --init src/ 4   # initialise at error level 4
<?php
// Psalm taint analysis catches this:
function showUser(PDO $db): void {
    /** @psalm-taint-source input */
    $id = $_GET['id'];
    // Psalm: TaintedSql — $id flows from HTTP input to query string
    $db->query("SELECT * FROM users WHERE id = $id");
}

3. PHP_CodeSniffer (PHPCS) — Coding Standards Enforcement

PHP_CodeSniffer is the de-facto tool for enforcing coding standards in PHP projects. It ships with built-in rulesets for PSR-1, PSR-2, PSR-12, WordPress, Squiz, and Zend, and teams can write custom XML sniff rules. Importantly, PHPCS is a style-only tool — it checks indentation, brace placement, spacing, naming conventions, and line length, but it does not catch logic bugs or type errors. Think of it as the PHP equivalent of Flake8's style-enforcement mode. The companion phpcbf binary auto-fixes many violations. Maintained by Squiz Labs under BSD-3-Clause.

composer require --dev squizlabs/php_codesniffer
./vendor/bin/phpcs src/ --standard=PSR12
<?php
// PHPCS PSR-12 flags this:
class foo {             // Error: Class name "foo" is not in PascalCase
  function Bar (){     // Error: Opening brace must be on next line
    $x=1;              // Error: No spaces around assignment operator
  }
}

4. PHP-CS-Fixer — Auto-Formatter

PHP-CS-Fixer is PHP's closest equivalent to Black (Python) or Prettier (JavaScript). Rather than just reporting violations, it rewrites your source files to conform to hundreds of configurable rules — covering everything from trailing commas in function calls to yoda conditions to multiline string formatting. The tool is idempotent: running it twice produces the same output, which makes it safe to add to pre-commit hooks without risk of infinite loops. PHP-CS-Fixer and PHPCS complement each other: run PHP-CS-Fixer first to auto-apply fixes, then run PHPCS to catch any remaining issues the fixer did not address. Maintained by the FriendsOfPHP organization under MIT license.

composer require --dev friendsofphp/php-cs-fixer
./vendor/bin/php-cs-fixer fix src/ --rules=@PSR12

5. Rector — AST-Based Automated Refactoring

Rector: Automated AST Refactoring PHP 7.4 (before) array_key_exists( $key, $arr ) $x = null; if (!$x) { $x = 'default'; } strpos($str, $n) !== false AST Transform Parse → Traverse Apply Rules ArrayKeyExistsToIsset NullCoalescingAssign StrposToStrContains PHP 8.4 (after) isset( $arr[$key] ) $x ??= 'default'; str_contains( $str, $n ) Legacy patterns rector.php rules applied Modern idioms Run with --dry-run first; re-run PHPStan after to verify type safety
Rector reads PHP 7.4 source into an AST, applies transformation rules (one per deprecated pattern), and writes modernized PHP 8.4 code back to disk.

Rector occupies a unique category: it is not a linter or a formatter, but an automated code rewriter. Rector parses PHP source into an AST, applies a configurable set of transformation rules, and writes the modified source back to disk. Its most compelling use case is automated PHP version upgrades — Rector can migrate a PHP 7.4 codebase to PHP 8.4 by automatically converting nullable type hints, adding match expressions, replacing strpos null checks with str_contains, converting create_function closures, and adding readonly property declarations where safe.

Rector pairs naturally with PHPStan: a common workflow is to run PHPStan to establish a pre-migration type-safety baseline, run Rector to apply the automated upgrade, then re-run PHPStan to verify the refactored code is still type-safe. Maintained by Tomas Votruba under MIT license.

composer require --dev rector/rector
# Preview changes without writing (dry-run)
./vendor/bin/rector process src/ --dry-run
<?php
// Rector upgrades this PHP 7.4 pattern automatically:
// BEFORE:
function getUser(?int $id): ?User {
    if ($id === null) { return null; }
    return strpos($id, 0) !== false ? find($id) : null;
}

// AFTER (PHP 8.x):
function getUser(?int $id): ?User {
    if ($id === null) { return null; }
    return str_contains((string)$id, '0') ? find($id) : null;
}

6. PHPMD — Heuristic Complexity Analysis

PHP Mess Detector (PHPMD) takes a different approach from PHPStan and Psalm: rather than type inference, it applies heuristic rules to detect code quality issues — excessive cyclomatic complexity, overly long classes and methods, deeply nested control structures, dead code (unused variables, parameters, and methods), and naming convention violations. PHPMD predates the modern PHP analysis era and is slower to evolve than PHPStan, but it remains useful for enforcing complexity budgets (for example, a maximum cyclomatic complexity of 10 per method) that type analyzers do not address. Maintained under BSD-3-Clause.

composer require --dev phpmd/phpmd
./vendor/bin/phpmd src/ text cleancode,codesize,unusedcode
<?php
// PHPMD flags this for excessive complexity (CyclomaticComplexity > 10):
class OrderProcessor {
    public function process(Order $o): string {
        if ($o->type === 'A') {
            if ($o->status === 'pending') {
                if ($o->amount > 100) {
                    // ... 8 more nested conditions
                }
            }
        }
        return 'done';
    }
}

7. Phan — Etsy's Incremental Analyzer

Phan was originally developed at Etsy and remains notable for two features: minimal runtime dependencies (it uses the php-ast native extension for parsing, which is dramatically faster than a pure-PHP parser) and genuine incremental analysis (only re-analyzing files that changed since the last run, with results cached in a SQLite database). For large codebases where PHPStan's full re-analysis is too slow, Phan's incremental mode can provide meaningful speedups in the edit-analyze loop. In practice, Phan has lost significant ground to PHPStan and Psalm in terms of rule quality, ecosystem, and active development. It is worth evaluating for very large monorepos where speed is the binding constraint. Maintained under Apache-2.0.

composer require --dev phan/phan
./vendor/bin/phan --allow-polyfill-parser -k .phan/config.php

8. Framework Extensions: Larastan, phpstan-symfony, and Friends

PHPStan's extension ecosystem deserves its own mention. Framework-specific PHPStan extensions teach the analyzer about magic methods, dynamic properties, and container bindings that raw PHP type inference cannot resolve. Larastan (maintained by Nuno Maduro, MIT) handles Eloquent relationships, model properties, facades, and helper functions in Laravel — without it, PHPStan would generate hundreds of false positives on any Laravel project. phpstan-symfony understands Symfony service containers and form types. phpstan-doctrine resolves Doctrine entity associations and repository return types. These are not separate tools; install them alongside PHPStan and reference them in phpstan.neon. They are what makes PHPStan practically viable for framework-based projects.

# Laravel + Larastan setup
composer require --dev nunomaduro/larastan
# phpstan.neon
# includes:
#   - ./vendor/nunomaduro/larastan/extension.neon
# parameters:
#   level: 6
#   paths: [app/]

Comparison Table: PHP Code Analysis Tools at a Glance

Tool Type License Best for PHP 8.4 support Speed Learning curve
PHPStan Type analyzer MIT Default type-safety gate; Laravel/Symfony projects Yes Fast Low–Medium
Psalm Type analyzer + SAST MIT Security-sensitive apps; taint tracking Yes Moderate Medium
PHPCS Style linter BSD-3 PSR-12 / WordPress / Symfony coding standards Yes Fast Low
PHP-CS-Fixer Auto-formatter MIT Auto-apply formatting; pre-commit hook Yes Fast Low
Rector AST refactoring MIT PHP version upgrades; framework migrations Yes Moderate Medium
PHPMD Heuristic linter BSD-3 Complexity budgets; dead code; naming Partial Moderate Low
Phan Type analyzer Apache-2.0 Large monorepos needing incremental analysis Partial Fast (incremental) High
Larastan PHPStan extension MIT Laravel Eloquent, facades, helpers Yes Fast Low

PHPStan vs. Psalm: Which Should You Pick?

PHPStan vs. Psalm: Five-Dimension Comparison PHPStan Psalm Speed Taint Analysis Ecosystem Plugin Count Learning Curve Fast ✓ Moderate Plugin only Native ✓✓ Excellent ✓✓ Good 50+ extensions ~15 plugins Low Medium Verdict PHPStan = default for most projects Psalm = add when taint / security is required Both MIT Both are MIT-licensed and support PHP 8.4 — differences are speed and security depth
PHPStan leads on speed, ecosystem breadth, and plugin count. Psalm leads on native taint analysis — the deciding factor for security-sensitive applications.

PHPStan and Psalm are both mature, actively maintained, MIT-licensed type analyzers for PHP. Both support generics via PHPDoc annotations. Both understand PHP 8.x union types, intersection types, and named arguments. Both have plugin architectures. The differences come down to three axes: speed, ecosystem breadth, and security depth.

PHPStan's Advantages

PHPStan is faster on large codebases — its analysis engine is more aggressively optimized and its result cache more effective at incremental re-analysis. More critically, PHPStan's plugin ecosystem is significantly broader. Larastan alone has over 5,000 GitHub stars and is the de-facto standard for PHP code analysis tools in Laravel projects. phpstan-symfony, phpstan-doctrine, phpstan-phpunit, and a dozen other framework-specific extensions handle the magic methods and dynamic patterns that make raw type inference produce false positives on framework code. PHPStan's strictness ladder (levels 0–10) is also better documented and more predictable than Psalm's error-level system, making it easier to set team-wide thresholds and enforce them in CI.

Psalm's Advantages

Psalm's killer feature is taint analysis. Enable it with --taint-analysis and Psalm traces the path of user-controlled data — $_GET, $_POST, $_COOKIE, database reads marked as tainted — through your entire call graph, flagging anywhere that data reaches a dangerous sink without sanitization. This catches SQL injection, stored XSS, and path traversal patterns that PHPStan's type-only analysis completely misses. Psalm also offers more granular annotation support: @psalm-pure enforces referential transparency, and @psalm-immutable prevents mutation of value objects — annotations that encode architectural invariants directly in the codebase.

Recommendation

Use PHPStan as the default for the vast majority of projects. Start at level 5 or 6, add the relevant framework extension, and enforce it in CI on every pull request. Add Psalm — specifically its taint analysis mode — only when your threat model genuinely requires systematic SQL injection and XSS tracking across the full call graph. Running both tools doubles your CI analysis time without proportional benefit unless taint tracking is a specific requirement. For broader context on SAST tooling choices, see our SAST tools comparison.

Setting Up a Modern PHP Code Analysis Workflow

4-Layer PHP Code Analysis Pipeline depth / time Layer 1 — Pre-commit PHP-CS-Fixer + PHPCS <1 s per commit Layer 2 — Local + CI PHPStan level 6+ 10–30 s every PR Layer 3 — CI Nightly Psalm + --taint-analysis 1–5 min main branch Layer 4 — Quarterly Rector upgrades (manual review) hours planned sprint Each layer catches different bugs — skip any layer and that bug category escapes into production
Fast layers (pre-commit, CI) run on every change; deeper layers (nightly Psalm taint, quarterly Rector) run on a schedule. The combination covers style, types, security, and upgrade debt.

A well-structured 2026 PHP code analysis workflow has four layers, each running at a different frequency. The goal is to keep the fast layers (pre-commit and local) under five seconds while reserving deeper checks for CI and scheduled runs.

  • Pre-commit (fast): PHP-CS-Fixer + PHPCS. Auto-format first, then check style. Both run in under two seconds on a typical changed-file set.
  • Local + CI (medium): PHPStan at level 6 or higher. Run locally on save (if your editor supports it) and as a required CI gate on every pull request.
  • CI nightly (deep): Psalm with --taint-analysis. Slower but catches security issues; run on the main branch nightly rather than on every commit.
  • Quarterly (upgrades): Rector. Schedule a periodic run to apply the latest PHP version upgrade rules and keep the codebase current with the language.

Step 1: Install the Tools

composer require --dev \
  phpstan/phpstan \
  vimeo/psalm \
  squizlabs/php_codesniffer \
  friendsofphp/php-cs-fixer \
  rector/rector

Step 2: Configure Pre-commit Hooks

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: php-cs-fixer
        name: PHP CS Fixer
        entry: ./vendor/bin/php-cs-fixer fix
        language: script
        types: [php]
        args: [--rules=@PSR12]

      - id: phpcs
        name: PHP CodeSniffer
        entry: ./vendor/bin/phpcs
        language: script
        types: [php]
        args: [--standard=PSR12]

Step 3: Add a GitHub Actions CI Pipeline

# .github/workflows/quality.yml
name: PHP Code Analysis

on: [push, pull_request]

jobs:
  analyse:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'

      - name: Install dependencies
        run: composer install --no-progress --prefer-dist

      - name: PHP CS Fixer (check only)
        run: ./vendor/bin/php-cs-fixer fix --dry-run --diff src/

      - name: PHPCS
        run: ./vendor/bin/phpcs src/ --standard=PSR12

      - name: PHPStan
        run: ./vendor/bin/phpstan analyse src/ --level=6 --no-progress

Step 4: Add Psalm Nightly for Taint Analysis

# In your workflow, add a scheduled job:
  psalm-nightly:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: { php-version: '8.4' }
      - run: composer install --no-progress --prefer-dist
      - name: Psalm taint analysis
        run: ./vendor/bin/psalm --taint-analysis

Why Visual Diff Review Belongs Before Static Analysis

3-Layer Code Review Pyramid Tests catches behavior, regressions PHPUnit Pest · PHPSpec Static Analysis catches types, style, security patterns PHPStan Psalm · PHPCS Human Visual Diff Review catches intent, logic, business rules invisible to automated tools ← Diff Checker fits here Foundation — run before static analysis Skipping any layer means that category of bug reaches production — all three layers are necessary
The three-layer review pyramid. Each layer catches what the others miss. Human diff review — the foundation — is the only layer that catches intent mismatches in type-safe, test-passing code.

Static analysis tools catch type errors, style violations, and dangerous data flows. Automated tests catch behavioral regressions. But there is a third category of bug that neither tool class reliably catches: intent mismatches — changes where the code is syntactically correct, type-safe, and passes all tests, but does something subtly different from what the developer intended. Copy-paste errors with near-identical variable names. Business rule conditions with a swapped > and >=. A refactored function that accidentally drops one clause of a compound condition. These bugs are invisible to analyzers because they represent correct code that encodes the wrong logic.

Visual diff review — comparing the exact lines that changed before running any automated tool — catches this category of bug by forcing a human to read the delta. When a reviewer can see precisely which lines were added, removed, or modified, they can reason about the intent of the change independently of whether the code compiles or passes analysis. The three layers complement each other: human diff review catches intent bugs, static analysis catches type and security bugs, tests catch behavioral regressions. Skipping the human-review layer means that intent bugs — which tend to be high-severity and slow to diagnose after deployment — survive all automated gates.

Diff Checker is a free Chrome extension (Manifest V3, version 1.1.11) that brings Monaco-based syntax highlighting — the same engine that powers VS Code — to PHP code review directly in the browser. It supports split view (side-by-side) and unified view, toggleable per session. Three diff algorithms are available: Smart Diff, Ignore Whitespace, and Classic (LCS), covering scenarios from whitespace-heavy reformats to algorithm comparisons. Unchanged regions collapse automatically with 0–5 lines of context, keeping long files navigable. One-click revert per change block lets reviewers restore individual sections without affecting surrounding changes.

The Normalize button handles a common PHP review friction point: auto-formatted files where PHP-CS-Fixer or PHPCS has changed whitespace throughout. Normalize strips incidental whitespace differences, leaving only substantive logic changes visible. The full diff computation is client-side — your PHP source never leaves the browser unless you explicitly opt into the AI Summary feature (which requires a user-supplied OpenAI key and is disabled by default). This matters for commercial PHP codebases where IP confidentiality is a concern.

The recommended workflow for PHP code review:

  1. Open Diff Checker and paste the before/after versions of the changed file.
  2. Review the highlighted changes to understand the logical intent of the diff.
  3. Run PHPStan and PHPCS in CI.
  4. Map each static analysis finding back to the specific changed lines you reviewed.
  5. Dismiss pre-existing findings; fix issues introduced by the current change.

This diff-first approach is especially effective for PHP refactors involving Rector or automated formatting passes, where a large number of lines change simultaneously. Being able to toggle between Smart Diff and Ignore Whitespace modes lets reviewers first confirm that the functional changes are correct, then verify that no unintended structural changes crept in. For teams comparing JSON configuration files (a common source of environment drift in PHP deployments), Diff Checker's key-sorting normalization also helps surface meaningful differences buried under key-order variations.

Frequently Asked Questions

PHPStan vs Psalm — which should I use?

PHPStan is the right default for most projects. It is faster, has a broader extension ecosystem (Larastan for Laravel, phpstan-symfony, phpstan-doctrine), and its eleven-level strictness ladder (0–10) makes incremental adoption straightforward. Psalm is the right choice when taint analysis is a specific requirement — it tracks $_GET, $_POST, and other tainted sources through the full call graph to dangerous sinks, catching SQL injection and XSS patterns that PHPStan's type-only analysis cannot see. Start with PHPStan at level 6; add Psalm only if your application handles sensitive user data and you need systematic taint tracking as a security gate.

Can I use PHPCS and PHP-CS-Fixer together?

Yes. They serve different roles. PHP-CS-Fixer is a formatter — it rewrites your files to match a defined style, auto-applying hundreds of rules without requiring manual fixes. PHPCS is a reporter — it detects violations against a named ruleset and fails the build if any remain. Run PHP-CS-Fixer first to auto-apply all fixes, then run PHPCS to catch any violations the fixer does not cover. In pre-commit hooks, PHP-CS-Fixer runs in fix mode; in CI, PHPCS runs in check-only mode and fails the build on remaining violations. The combination gives you both automated fixing and a hard gate — without duplicate effort between the two tools.

What does Rector actually do?

Rector parses your PHP source into an AST, applies a set of transformation rules, and writes the modified code back to disk. It does not report issues — it fixes them automatically. The most common use case is automated PHP version upgrades: Rector can migrate a PHP 7.4 codebase to PHP 8.4 by adding union types, converting create_function closures to arrow functions, replacing null-check patterns with str_contains or the null-safe operator, and adding readonly declarations where safe. Run Rector with --dry-run first to preview changes, then apply and re-run PHPStan to verify the refactored code is still type-safe.

How do I integrate PHP static analysis into GitHub Actions?

Create a .github/workflows/quality.yml file that triggers on push and pull_request. Use the shivammathur/setup-php action to install PHP 8.4, run composer install, then add separate steps for PHP-CS-Fixer in --dry-run mode, PHPCS with your standard, and PHPStan at your chosen level. Each step exits non-zero on violations, so the workflow fails and blocks merging. The complete YAML configuration in the workflow section above can be copied directly into your repository. For teams using the tools covered in our broader static code analysis tools guide, the same layered approach applies regardless of language.

Are PHP code analysis tools free?

Yes. Every tool in this guide is free and open-source: PHPStan (MIT), Psalm (MIT), PHP_CodeSniffer (BSD-3), PHP-CS-Fixer (MIT), Rector (MIT), PHPMD (BSD-3), Phan (Apache-2.0), and Larastan (MIT). There are no SaaS subscriptions, usage limits, or cloud accounts required. The complete PHP code analysis tools stack — including CI integration — runs entirely on your own infrastructure with zero license cost, making it accessible to projects of every size from solo indie projects to large engineering teams.