swissspidy/phpstan-no-private
PHPStan extension that reports deprecation warnings when code uses “pseudo-private” elements marked with @access private. Helps prevent relying on internal classes, methods, functions, or properties. Easy install via Composer with optional extension-installer support.
Installation:
composer require --dev swissspidy/phpstan-no-private
Use phpstan/extension-installer for automatic setup (recommended):
composer require --dev phpstan/extension-installer
Or manually include in phpstan.neon:
includes:
- vendor/swissspidy/phpstan-no-private/rules.neon
First Use Case: Run PHPStan on a Laravel service with a private method:
vendor/bin/phpstan analyse app/Services/UserService.php
If UserService has a @access private method called externally, PHPStan will emit a deprecation warning.
Pre-Commit Hooks:
Integrate PHPStan with Git hooks (e.g., husky) to catch violations early:
vendor/bin/phpstan analyse --level=5 --memory-limit=1G
Exit with non-zero status on errors to block commits.
CI/CD Pipeline: Add to Laravel’s GitHub Actions workflow:
- name: PHPStan (No Private)
run: vendor/bin/phpstan analyse --level=5 --error-format=github
Service Containers:
Use protected properties instead of private to avoid false positives while maintaining encapsulation:
// Before (triggers warning)
private $apiClient;
// After (recommended)
protected $apiClient;
Models and Entities: Replace private properties with public getters/setters or constructor injection:
// Before (triggers warning)
private $userId;
// After
public function __construct(private int $userId) {}
Whitelist Classes:
Exclude legacy classes in phpstan.neon:
parameters:
excludeClasses:
- 'App\\Legacy\\*'
Partial Enforcement:
Use --level=3 (deprecation) for new code while ignoring legacy:
vendor/bin/phpstan analyse --level=3 --ignore-errors=*
paths:
- src/
- app/
ignorePaths:
- tests/
2. **PHPStan 2.0 Migration**:
- Ensure `phpstan/phpstan` is **v2.0+** in `composer.json`.
- Update `phpstan.neon` to use `level: 10` (or higher) for stricter checks:
```neon
level: 10
```
3. **Legacy Code Overload**:
Use `--generate-baseline` to suppress warnings temporarily:
```bash
vendor/bin/phpstan analyse --generate-baseline
Commit the baseline and refactor incrementally.
Verbose Output:
Run with --verbose to diagnose rule application:
vendor/bin/phpstan analyse --verbose
Rule-Specific Errors:
If a rule fails silently, check phpstan.neon for misconfigured includes:
includes:
- vendor/swissspidy/phpstan-no-private/extension.neon # Correct path
Custom Rules:
Extend the package by creating a custom PHPStan rule (e.g., for @access protected):
// app/Rules/NoProtectedRule.php
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
class NoProtectedRule implements Rule {
public function getNodeType(): string { return 'Php\Method'; }
public function processNode(Node $node): array {
if ($node->isPrivate() || $node->isProtected()) {
return [RuleErrorBuilder::message('Protected/private methods are disallowed')->build()];
}
return [];
}
}
Integration with Laravel Testing:
Use phpstan/extension-installer to auto-load rules in phpstan.neon:
extensions:
- PhpStanNoPrivate\NoPrivateExtension
How can I help you explore Laravel packages today?