shipmonk/phpstan-rules
40 super-strict PHPStan rules from ShipMonk to close gaps even in extra-strict setups. Installs as an extension, configurable per rule (enable/disable, tweak defaults), with options like safer comparisons, enum generics checks, and more.
composer require --dev shipmonk/phpstan-rules
phpstan.neon:
includes:
- vendor/shipmonk/phpstan-rules/rules.neon
vendor/bin/phpstan analyse
Start with forbidCast and forbidArithmeticOperationOnNonNumber—these catch common type-safety issues early. Example:
// Fails: forbidden cast
$arr = (array) null;
// Fails: arithmetic on non-number
$str = "10";
$str + 5; // Error
Incremental Adoption:
enforceNativeReturnTypehint and enforceClosureParamNativeTypehint first to modernize type hints.enforceReadonlyPublicProperty (PHP 8.1+) or forbidCheckedExceptionInCallable (for exception safety).Team Onboarding:
classSuffixNaming to enforce naming conventions (e.g., *Test for tests).forbidCustomFunctions to block legacy patterns (e.g., call_user_func_array).Legacy Code:
! in config:
parameters:
shipmonkRules:
forbidCast:
blacklist!: ['(array)'] # Only block (array) casts
Enum Handling:
Use enforceEnumMatch to replace verbose if-else chains with match expressions:
// Before (error-prone)
if ($status === Status::PENDING) { ... }
// After (recommended)
return match ($status) {
Status::PENDING => 'pending',
Status::APPROVED => 'approved',
};
Immutable Properties:
Enforce readonly with enforceReadonlyPublicProperty (PHP 8.1+):
class User {
public readonly string $name; // Enforced
public string $email; // Fails
}
Iterator Safety:
Require explicit iterator_to_array($iterator, false) with enforceIteratorToArrayPreserveKeys to avoid silent key collisions.
BackedEnum Generics:
backedEnumGenerics requires a custom stub file (see ShipMonk’s guide).phpstan.neon:
parameters:
stubFiles:
- vendor/shipmonk/phpstan-rules/BackedEnum.php.stub
False Positives:
forbidCheckedExceptionInCallable may flag Symfony’s Question::setValidator (allow via config):
parameters:
shipmonkRules:
forbidCheckedExceptionInCallable:
allowedCheckedExceptionCallables:
'Symfony\Component\Console\Question::setValidator': 0
PHP Version Limits:
enforceReadonlyPublicProperty or enforceNativeReturnTypehint require PHP 8.1+. Use ignoreErrors to bypass:
ignoreErrors:
- '#^Cannot use readonly property on PHP < 8.1$#'
Rule-Specific Config:
Override defaults with ! to avoid merging:
parameters:
shipmonkRules:
forbidCast:
blacklist!: ['(array)'] # Overrides all defaults
Selective Enforcement: Disable all rules first, then enable only needed ones:
parameters:
shipmonkRules:
enableAllRules: false
enforceNativeReturnTypehint:
enabled: true
Custom Rules:
Extend the package by adding new rules to rules.neon:
includes:
- vendor/shipmonk/phpstan-rules/rules.neon
- path/to/custom-rules.neon
CI Integration:
Use PHPStan’s --error-format=json to parse results in CI:
vendor/bin/phpstan analyse --error-format=json | jq '.files[] | select(.errors | length > 0)'
Performance: Exclude tests or large directories:
paths:
- src/
- tests/ # Excluded
How can I help you explore Laravel packages today?