thecodingmachine/phpstan-safe-rule
PHPStan rule that detects calls to unsafe core PHP functions and suggests the thecodingmachine/safe variants, which throw exceptions instead of returning false on error. Helps catch unsafe function usage during static analysis.
Architecture fit
DynamicReturnTypeExtensions (preg_match, preg_replace_callback, json_decode, ReplaceSafeFunctions) — shipped as a Composer package. It contributes zero code to the application runtime, which makes it one of the lowest-blast-radius dependencies a TPM can approve: nothing ships, nothing executes in production, rollback is deleting a line from phpstan.neon.false and suggests the Safe\* equivalent. Without thecodingmachine/safe installed and adopted, the findings have no remediation path and the package is pure noise. Treat "adopt Safe" and "adopt this rule" as a single decision.Integration feasibility
composer require --dev thecodingmachine/phpstan-safe-rule, then include extension.neon in phpstan.neon (or rely on phpstan/extension-installer). v0.1.4 onward supports the installer.safe at ^1.2/^2/^3 (v1.4 explicitly flags compatibility with Safe v3). The PHPStan 2 requirement is usually the largest hidden cost in a Laravel estate, because it drags Larastan along with it.JSON_THROW_ON_ERROR (including as a named argument, v1.4.1), typed $matches for preg_match, json_decode return types, and first-class callables. new DateTime / new DateTimeImmutable detection has existed since v1.0.Technical risk
extension.neon produces a clean, green build that enforces nothing. This is worse than not adopting the tool, because it manufactures false confidence in a control you told stakeholders you have. Verify with a deliberate unsafe call in a throwaway file.Key questions
safe actually adopted, in evaluation, or aspirational? If aspirational, this is a two-part commitment, not a one-line install.file_get_contents, fopen, JSON without JSON_THROW_ON_ERROR, preg_*, DateTime) map to our real incident history, or is this generic hygiene?@phpstan-ignore creep?Stack fit
phpstan analyse. The only structural interaction is with Larastan — both are PHPStan extensions, so include ordering and version alignment must be explicit.Safe\*) may not match house style, and the value proposition weakens.Migration path
extension.neon, run a full analysis without failing the build, and count findings by directory and by function. That count is your business case and your schedule input.safe alongside it in the same service; remediate one or two modules by hand to validate that the Safe\* replacements actually fit the codebase's error handling.Compatibility and sequencing
safe → adopt this rule with baseline → burn down. Adopting the rule before the analyzer upgrade forces a version of the rule that will be immediately obsoleted.safe v3, which the rule explicitly supports from v1.4; mixing a Safe v2 runtime with assumptions from v3 docs (or vice versa) is a needless source of confusion."thecodingmachine/phpstan-safe-rule": "1.4.3" or exact-current) and upgrade it in lockstep with PHPStan via the same dependency-bot PR group.Maintenance
safe + the rule), plus their coupling to PHPStan's major version cadence. Budget a recurring line item: one upgrade ticket per PHPStan major, owner-named.Support
Scaling
Failure modes
Safe\* converts a silent false into a thrown exception; code that previously limped through a failed file_get_contents now fails loudly. That is the desired outcome, but it means every remediation is a behavior change that needs a handler and, where it matters, an alert. Sequence remediations with normal change control rather than bundling them into a lint cleanup.Ramp-up
Safe\*, here's why, here's how to suppress legitimately"): roughly 2–5 engineer-days for a mid-sized Laravel codebase, plus ongoing triage.How can I help you explore Laravel packages today?