nowo-tech / phpstan-frankenphp
PHPStan rules to migrate PHP apps from PHP-FPM to FrankenPHP classic mode, then worker mode. Rules are split by migration level with documented justification and application order.
Package info
github.com/nowo-tech/PhpStanFrankenPhp
Type:phpstan-extension
pkg:composer/nowo-tech/phpstan-frankenphp
Fund package maintenance!
Requires
- php: >=8.1 <8.6
- phpstan/phpstan: ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^10.0 || ^11.0
- rector/rector: ^2.0
- symfony/http-foundation: ^6.4 || ^7.0 || ^8.0
- symfony/process: ^6.4 || ^7.0 || ^8.0
- symfony/service-contracts: ^2.5 || ^3.0
This package is auto-updated.
Last update: 2026-07-22 16:03:23 UTC
README
⭐ Found this useful? Install from Packagist and star the repository on GitHub.
PHPStan rules that help you migrate from PHP-FPM to FrankenPHP classic, then to worker mode. Rules are split by level, documented with justification, and shipped with demos for every case.
Documentation
- Installation
- Configuration
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
Additional documentation
- Rule catalog
- Migration guide (FPM → classic → worker)
- FrankenPHP demos
- Demos
- GitHub Actions CI requirements
- Branching strategy
Why
FrankenPHP classic already changes process lifetime compared to FPM (exit/die, FastCGI APIs, unbounded I/O). Worker mode keeps the app in memory: statics, globals, and $_ENV mutations survive across requests. This extension surfaces those sites in CI so you can fix them in order.
Fixes stay FPM-compatible. The suggested remediations are portable patterns (no FrankenPHP-only APIs). They make the codebase more solid on FPM and safe for worker mode. Details: docs/MIGRATION.md — FPM compatibility.
Levels (application order)
| Order | Ruleset | When |
|---|---|---|
| 1 | ruleset-classic.neon |
Moving FPM → FrankenPHP classic |
| 2 | ruleset-worker.neon |
Enabling FrankenPHP worker |
| 2b | ruleset-worker-strict.neon |
Optional: also flag $_GET/$_POST/… |
| 3 | ruleset-hardening.neon |
Production hardening (timeouts, fork, sleep) |
Full catalog: docs/RULES.md.
Installation
composer require --dev nowo-tech/phpstan-frankenphp
Enable levels intentionally (rules are not auto-enabled by extension.neon):
# phpstan.neon includes: - vendor/nowo-tech/phpstan-frankenphp/ruleset-classic.neon # - vendor/nowo-tech/phpstan-frankenphp/ruleset-worker.neon # - vendor/nowo-tech/phpstan-frankenphp/ruleset-worker-strict.neon # - vendor/nowo-tech/phpstan-frankenphp/ruleset-hardening.neon
See docs/CONFIGURATION.md and docs/RULES.md.
Quick example
// Flagged by classic rules: exit(1); fastcgi_finish_request(); $process->setTimeout(null); // Flagged by worker rules: private static array $cache = []; static $count = 0; $_ENV['TOKEN'] = $requestToken; // Flagged by hardening rules: set_time_limit(0); sleep(5); pcntl_fork();
Demos
Symfony 8 + FrankenPHP
make -C demo/symfony8 up # Demo started at: http://localhost:8090 make -C demo/symfony8 phpstan-classic # expect findings on AntiPattern/
FrankenPHP worker mode: supported (tested in the Symfony 8 demo with FRANKENPHP_MODE=worker by default). See docs/DEMO-FRANKENPHP.md.
Fixture demos
Intentional violations and clean counterparts under demo/:
composer demo-classic # expect findings composer demo-worker composer demo-hardening composer demo-classic-good # must be clean
Tests and coverage
make test
make test-coverage
- PHPUnit suites:
tests/Rule(RuleTestCase per rule),tests/Unit(helpers / edge branches),tests/Integration(neon wiring). - Line coverage on
src/: 100% (enforced viacomposer coverage-check/ CI on PHP 8.2).
Development
make setup-hooks make ensure-up make qa make demo-all
License
MIT — see LICENSE.