The Case for Strict PHPStan Baselines in Enterprise Codebases
Source: Dev.to
Problem
Modernizing a legacy PHP application presents a paradox: you critically need strict static analysis to prevent future bugs, but turning on a tool like PHPStan immediately throws thousands of errors, completely breaking the CI pipeline.
During a recent stabilization project on an enterprise platform (rlh‑core), the codebase had excellent business logic but was rife with missing return types, loose array definitions, and checks like empty($message) instead of strict null checks.
A naive approach would be to halt feature development for a month and force the team to fix all existing errors until PHPStan returns green—an approach that is financially unsustainable.
Leaving PHPStan disabled, however, allows technical debt to accumulate unchecked.
Solution: PHPStan Baseline Pattern
-
Configure PHPStan at maximum strictness (Level 8).
-
Run it against the entire codebase and pipe the output into a baseline file:
vendor/bin/phpstan analyse -c phpstan.neon --error-format=raw > phpstan-baseline.neonThe generated
phpstan-baseline.neonacts as a cryptographic signature of the existing technical debt, telling the CI pipeline to ignore those specific errors on the identified lines. -
Commit the baseline. The CI pipeline now passes (green) while the strict Level 8 rules are active for all new code.
-
Enforce a baseline rule: when a file is touched for a new feature, any baseline errors in that file must be resolved.
-
Automatic cleanup: when an engineer fixes an issue (e.g., replaces
empty()with a strict null check), PHPStan detects that the error no longer exists and prompts the removal of the corresponding entry from the baseline (reportUnmatched: true).
Results
- Over six months, the baseline shrank from ~5,000 errors to under 300 without a dedicated refactoring sprint.
- New code that violates strict rules (missing return types, unchecked array keys, etc.) fails the build, preventing the introduction of additional debt.
- The application became highly deterministic and type‑safe by enforcing a strict boundary on new code while gradually reducing legacy issues.
Takeaway
When dealing with enterprise technical debt, the strategy isn’t to “burn the house down”; it’s to stop adding fuel to the fire by enforcing strict static analysis for all new development while systematically eliminating existing problems.
Originally published at VictorStack AI — Drupal & WordPress Reference.