shipmonk/phpstan-rules
40 super-strict PHPStan rules from ShipMonk to plug gaps in extra-strict setups. Install via Composer, include rules.neon, then enable/disable or tune rules per-project. Targets tricky PHP edge cases like unsafe comparisons, casts, arrays, enums and more.
readonly properties in PHP 8.2+ while ignoring rules like classSuffixNaming for legacy code).enforceReadonlyPublicProperty skips PHP 8.0), reducing friction in polyglot environments.phpstan.neon in phpstan package). No Laravel-specific hooks required.enforceNativeReturnTypehint works with Laravel’s return type hints in controllers/services). Compatible with:
phpstan-baseline for incremental adoption..env-driven APP_DEBUG) can toggle rules via NEON (e.g., disable forbidCast in local dev).| Risk Area | Mitigation |
|---|---|
| Rule Overhead | Start with a subset of rules (e.g., enforceNativeReturnTypehint, forbidArithmeticOperationOnNonNumber) and measure CI/CD impact before full adoption. |
| False Positives | Leverage PHPStan’s ignoreErrors or rule-specific configs (e.g., allowNumericString: true for forbidArithmeticOperationOnNonNumber). |
| Backward Compatibility | Use excludePaths in NEON to opt-out legacy codebases (e.g., app/OldCode/). Rules like classSuffixNaming can be gradually enforced via superclassToSuffixMapping. |
| Performance | Rules like enforceIteratorToArrayPreserveKeys are lightweight; benchmark in CI to ensure no slowdowns. Cache PHPStan results (--generate-baseline) to offset initial overhead. |
| Dependency Bloat | Package is ~1MB (Composer); negligible compared to Laravel’s core dependencies. |
enforceReadonlyPublicProperty may break legacy code; should it be phased?forbidCheckedExceptionInCallable for service containers, enforceNativeReturnTypehint for API responses).DB::raw() in queries)? Extend via PHPStan’s extension system.forbidCast matters for Eloquent queries")?phpstan.neon:
includes:
- vendor/shipmonk/phpstan-rules/rules.neon
parameters:
shipmonkRules:
enforceNativeReturnTypehint: true
forbidCheckedExceptionInCallable:
allowedCheckedExceptionCallables:
'Illuminate\Database\Connection::transaction': 0
forbidCast for (array) in Eloquent collections (use blacklist!: ['(array)']).Symfony\Component\Console\Command\Command in classSuffixNaming for Artisan commands.enforceEnumMatch improve test reliability by catching incomplete match statements.docker-compose.yml or Valet templates.vendor/bin/phpstan analyse --generate-baseline app src
enforceIteratorToArrayPreserveKeys, forbidArithmeticOperationOnNonNumber).enforceNativeReturnTypehint, allowComparingOnlyComparableTypes).forbidCheckedExceptionInCallable).forbidCast blacklist for Eloquent).BackedEnum.php.stub for custom enums).--level 5 in PHPStan).| Laravel Component | Compatibility Notes |
|---|---|
| Eloquent | Disable (array) casts in forbidCast to avoid breaking Model::toArray(). |
| Service Container | forbidCheckedExceptionInCallable may flag closures in bind(); whitelist Illuminate\Container\Container::call(). |
| Artisan Commands | Configure classSuffixNaming to enforce Command suffix for \Symfony\Component\Console\Command\Command subclasses. |
| Blade Templates | Rules like enforceNativeReturnTypehint don’t apply; exclude resources/views from analysis. |
| Legacy Code (PHP < 8.0) | Disable PHP-version-specific rules (e.g., enforceReadonlyPublicProperty) via NEON. |
readonly, enums, and match support).enforceEnumMatch).enforceNativeReturnTypehint → allowComparingOnlyComparableTypes.enforceReadonlyPublicProperty (PHP 8.2+).forbidCheckedExceptionInCallable → forbidCheckedExceptionInYieldingMethod.classSuffixNaming, enforceClosureParamNativeTypehint.analyze with --memory-limit=1G to avoid OOM in large codebases.--error-format=github-pr-check for PR-level feedback.forbidCast may evolve; use ! in NEON to override defaults (e.g., blacklist!: ['(array)']).config/phpstan.php (e.g., custom superclassToSuffixMapping).PHPSTAN_RULES_STRICT=1 in CI).How can I help you explore Laravel packages today?