Help us shape the future of Go! Take the 2026 Go Developer Survey

igor-php

command module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2026 License: MIT Imports: 13 Imported by: 0

README ΒΆ

πŸ§Ÿβ€β™‚οΈβš‘ Igor-Php

Igor PHP Logo

The faithful assistant for your FrankenPHP Workers.

igor-php is an ultra-fast static linter written in Go that prepares your Symfony application for the persistent memory model of FrankenPHP.

Like the legendary assistant, igor checks every connection and part of your application to ensure it won't "blow up" when the lightning strikes (Worker Mode).


✨ Highlights

  • ⚑ Lightning Fast: Scans hundreds of files in milliseconds using Go's native multi-threading.
  • πŸ” Deep Audit: Automatically detects Symfony projects and audits every shared service defined in the container, including those in vendor/ and external bundles.
  • 🎯 Surgical Precision: Detects complex state mutations ($this->prop[], static::$prop, increments) without false positives.
  • 🧠 Intelligent: Verifies not just the presence of ResetInterface, but ensures all mutated properties are correctly reset. Automatically ignores readonly properties and classes (PHP 8.1+) as they are immutable by design.
  • πŸ›‘οΈ Safety First: Catches dangerous exit() or die() calls, and warns about PHP Superglobals ($_GET, $_POST, etc.) or local static variables that could leak state between requests.
  • πŸ”‡ Zero Noise: Automatically ignores Symfony\ and Doctrine\ namespaces, and common data folders (Entity, Dto, ApiResource).
  • πŸ“¦ Project vs. Vendor: Clear separation between your code and third-party dependencies, with tailored recommendations for each.
  • 🎯 Selective Ignore: Skip specific lines using the // @igor-ignore comment.

πŸ“‹ Prerequisites

  • Go: Required to compile or install the binary.
  • PHP 8.1+: Required for the Deep Audit mode. Igor uses PHP Reflection to precisely locate service files within your project and vendor/ directory. Without PHP, Igor will fall back to a standard directory scan.

πŸš€ Installation

composer require --dev igor-php/igor-php
Via Go
go install github.com/igor-php/igor-php@latest

πŸ› οΈ Usage

πŸͺ„ Quick Start

Igor can automatically detect your project type Symfony and generate a default configuration for you:

# Initialize igor.json
igor-php init
πŸ” Audit your project

Once initialized (or using defaults), let Igor audit your project:

# Standard usage
igor-php .

# Custom console path, environment and verbose mode
igor-php --console app/console --env stage --verbose .

πŸ§ͺ See it in Action

Want to understand why Igor is vital for your Worker environment? Check these real-world scenarios from our Leak Lab:

1. Memory Pressure (The "BOOM" effect) 2. Global State Poisoning
Memory Leak Demo Global State Leak Demo
Adding data to a shared service without reset will accumulate in RAM until the worker crashes. Modifying global PHP settings (like timezone) "poisons" the worker thread for all future requests.
πŸ›‘οΈ Igor's Verdict: Catching them all in < 1s

Igor Scan Demo Igor identifies all leaks (Static, Stateful, Incomplete Reset) and dangerous global function calls automatically.


πŸ§ͺ Try the Leak Lab yourself!

We've built an interactive laboratory using Symfony and FrankenPHP. You can run it locally with Docker and see the memory leaks with your own eyes.

Explore the Igor Leak Lab β†’


Deep Audit Mode (Symfony)

When a Symfony project is detected, Igor combines three layers of discovery to ensure maximum reliability:

  1. Level 1: Project Code (Recursive Scan): Igor scans all PHP files in your project directory (excluding vendor, var, tests, etc.). This ensures that even if Symfony "inlines" or "hides" a service for optimization, Igor will still find and audit it.
  2. Level 2: Trusted Vendors (Recursive Scan): By using the scan_vendors configuration, you can force a full recursive scan of specific vendor directories (like your company's internal bundles).
  3. Level 3: Global Ecosystem (Smart Scan): Igor queries the Symfony Service Container to identify all other active shared services in the vendor/ directory. This covers the "long tail" of third-party dependencies without the performance hit of scanning tens of thousands of files.
Example Output
--- πŸ“‚ PROJECT SERVICES ---

πŸ“‚ src/Service/MyService.php
  [PROJECT] ❌ Mutation of state 'cache' in MyService::getData().
  42 | $this->cache = $result;
  πŸ’‘ Hint: State mutations persist across requests in Worker mode.

--- πŸ“¦ VENDOR SERVICES (THIRD-PARTY) ---

πŸ“‚ vendor/acme/bundle/Service.php
  [VENDOR] ❌ Mutation of state 'static::$globalCache' in ::()
  20 | self::$globalCache = "value";
  πŸ’‘ Hint: State mutations persist across requests in Worker mode.

--- 🏁 DEEP AUDIT COMPLETE ---
Total unique service files: 15
βœ… OK (Stateless):           13
❌ KO (Dangerous State):     2 (Project: 1, Vendor: 1)
⚠️  WARN (Review reset):      0 (Project: 0, Vendor: 0)
Time taken: 1.2s

πŸ’‘ RECOMMENDATIONS:
  [PROJECT] Since this is your code, you should refactor these services to be stateless
            or implement ResetInterface to clear the state between requests.
  [VENDOR]  This is third-party code. If you can't fix it, consider setting a 'max_requests' limit
            in your Worker configuration to mitigate memory leaks.

βš™οΈ Configuration

You can customize Igor's behavior by creating an igor.json file at the root of your project:

{
  "exclude": ["vendor", "tests", "Entity"],
  "safe_namespaces": ["Symfony\\", "Doctrine\\", "My\\Safe\\Namespace\\"],
  "scan_vendors": ["my-company/internal-bundle", "trusted/library"],
  "console_path": "bin/console",
  "env": "prod",
  "verbose": false
}
  • exclude: List of directories to skip during indexing.
  • safe_namespaces: Igor will ignore state mutations in classes starting with these prefixes.
  • scan_vendors: List of sub-directories within vendor/ to scan recursively. Useful for internal bundles that might not be registered as official Symfony services but still run in your process.
  • console_path: Custom path to the Symfony console binary. Defaults to bin/console.
  • env: Symfony environment to use for container analysis. Defaults to prod.
  • verbose: Enable verbose output to see skipped services and reasons. Defaults to false.
Selective Ignoring

If you have a specific line that you know is safe, you can use the // @igor-ignore annotation:

// @igor-ignore
$this->cache = $data; // This line will be ignored

$this->counter++; // @igor-ignore - This line too

πŸ” Understanding Deep Audit Filtering

When using the Deep Audit mode (Symfony), Igor might analyze fewer services than your total container count. Use the --verbose flag to see exactly why a service was skipped. Common reasons include:

  • πŸ”„ Duplicate File: Multiple Service IDs (aliases, locators, etc.) pointing to the same PHP file. Igor only audits each unique file once.
  • ♻️ Non-shared (Prototype): Services marked as shared: false are recreated on every request and don't persist state between workers. They are safe by design.
  • Ξ» Closures / Synthetic: Services that don't map to a physical PHP class (like Closures or synthetic services) cannot be statically analyzed.
  • πŸ›‘οΈ Safe Namespace: The class belongs to a namespace defined in safe_namespaces (like Symfony\ or Doctrine\).

πŸ€– CI/CD Integration

Igor is designed to work out-of-the-box in your CI pipelines. It will exit with code 1 if any error is found, effectively stopping your build.

GitHub Actions support

When running inside GitHub Actions, Igor automatically generates inline annotations. This means errors will appear directly in your Pull Request review, right next to the code causing the issue.

Igor GitHub Review

GitHub Actions Example
name: Static Analysis
on: [push, pull_request]

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

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'

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

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: Run Igor
        run: |
          go install github.com/igor-php/igor-php@latest
          igor-php .

πŸ™ Credits & Inspirations

  • Phanalist: Special thanks to phanalist and its rule E0012 (Stateful Service) which inspired Igor's core mutation detection logic.
  • Gemini CLI: This project was built with the help of Gemini CLI.
  • FrankenPHP: For the amazing server that makes these checks necessary!

πŸ“„ License

MIT

Documentation ΒΆ

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL