PHPStan Static Analyzer
| Analyzer ID | Category | Severity | Time To Fix |
|---|---|---|---|
phpstan | ✅ Reliability | Critical | 120 minutes |
What This Checks
The PHPStan analyzer is a consolidated analyzer. It runs PHPStan once and categorizes issues into 16 distinct categories:
- Compile Errors - Syntax errors, colliding
useimports, and methods, properties, constants, enum cases or parameters declared twice, all of which PHP refuses to load - Dead Code - Unreachable statements, unused variables, and code with no effect
- Deprecated Code - Usage of deprecated methods, classes, and functions
- Foreach Iterable Issues - Invalid foreach usage with non-iterable values
- Invalid Function Calls - Calls to undefined or incorrectly parameterized functions
- Invalid Imports - Invalid use statements for non-existent classes
- Invalid Method Calls - Calls to undefined or incorrectly parameterized methods
- Invalid Method Overrides - Incompatible method signature overrides
- Invalid Offset Access - Invalid array offset access and type mismatches
- Invalid Property Access - Access to undefined or inaccessible properties
- Missing Model Relations - References to non-existent Eloquent relations
- Missing Return Statements - Methods with missing return statements
- Undefined Constants - References to undefined constants
- Undefined Variables - References to undefined variables
- Used Void Results - Using the result of a void function, method, closure,
matchoryield, which is always null - Other PHPStan Issues - PHPStan errors that no specific category claims
Each issue is automatically categorized and reported with category-specific recommendations.
Why It Matters
- Type safety - Catches type errors before they cause runtime failures
- Early detection - Finds bugs during development, not in production
- Comprehensive coverage - Detects 16 categories of reliability issues in one analyzer
- Cleaner codebase - Removes dead code and unused variables
- Better maintainability - Ensures deprecated code is updated
- Laravel-specific - Detects issues with Eloquent relations and Laravel patterns
How to Fix
Quick Fix (45 minutes)
Run PHPStan to see all issues:
php artisan shield:analyze --analyzer=phpstanReview the categorized issues and fix the most critical ones first:
// ❌ BAD - Undefined variable
public function process()
{
return $undefinedVariable; // Critical issue
}
// ✅ GOOD - Variable defined
public function process()
{
$result = 'processed';
return $result;
}Proper Fix (120 minutes)
- Fix compile errors first - When PHPStan cannot process a file, it stops there and drops every other finding in the project. A syntax error does this, and so can two
useimports that claim the same name. The result names the file and line, after any findings that were reported:
PHPStan stopped at file(s) it could not process, so the rest of the project was not analysed: app/Services/InvoiceService.php:12That error is reported as Critical whatever its category, so the run fails the build. Fix the file, then rerun the analyzer to see the findings for the rest of the project:
// ❌ Before: a missing semicolon is a syntax error, so PHPStan cannot parse the file
public function total(): int
{
return $this->lines->sum('amount')
}
// ✅ After
public function total(): int
{
return $this->lines->sum('amount');
}Other compile errors, such as a method declared twice, are also reported under Compile Errors at Critical, but PHPStan still analyses the rest of the project.
- Configure PHPStan level - Publish the config:
php artisan vendor:publish --tag=shieldci-configThen start with level 5, increase gradually in config/shieldci.php:
'analyzers' => [
'reliability' => [
'enabled' => true,
'phpstan' => [
'level' => 5, // 0-9 on PHPStan 1, 0-10 on PHPStan 2, or 'max'; higher is stricter
// Optional: Override global paths (uses 'paths.analyze' by default)
// 'paths' => ['app', 'routes'],
'categories' => [
'compile-errors',
'dead-code',
'deprecated-code',
'foreach-iterable',
'invalid-function-calls',
'invalid-imports',
'invalid-method-calls',
'invalid-method-overrides',
'invalid-offset-access',
'invalid-property-access',
'missing-model-relation',
'missing-return-statement',
'undefined-constant',
'undefined-variable',
'used-void-result',
'other',
],
'disabled_categories' => [
// Optionally disable specific categories
],
],
],
],- Fix issues by category - Address high-severity issues first:
// Invalid Method Call
// ❌ Before
$user->undefinedMethod();
// ✅ After
$user->existingMethod();
// Missing Return Statement
// ❌ Before
public function calculate(int $a, int $b): int
{
$result = $a + $b;
// Missing return!
}
// ✅ After
public function calculate(int $a, int $b): int
{
$result = $a + $b;
return $result;
}
// Undefined Variable
// ❌ Before
if ($condition) {
$value = 'something';
}
return $value; // $value might not be defined
// ✅ After
$value = null; // Initialize first
if ($condition) {
$value = 'something';
}
return $value;
// Used Void Result
// ❌ Before
$sent = $mailer->send($message); // send() returns void, so $sent is always null
// ✅ After
$mailer->send($message);- Enable/disable categories - Focus on specific issue types:
// Disable less critical categories temporarily
'disabled_categories' => [
'dead-code', // Fix later
],- Adjust PHPStan level - Increase strictness over time:
// Start at 5 (balanced), then raise one level at a time as you fix issues:
// 6 → 7 → 8 (strict) → 9 (maximum on PHPStan 1) → 10 (maximum on PHPStan 2)
'level' => 5,Set level once. If the array contains the key more than once, PHP keeps only the last value.
PHPStan Levels:
- Level 0-2: Very lenient, good for legacy code
- Level 3-5: Balanced, recommended for most projects
- Level 6-8: Strict, ideal for new projects
- Level 9: Strict about explicit
mixedtypes; the maximum on PHPStan 1 - Level 10: PHPStan 2 only; also strict about implicit
mixed(missing types); the maximum on PHPStan 2
Level 10 requires PHPStan 2. Check your installed version before going past 9:
vendor/bin/phpstan --versionSet 'max' to run the highest level your installed PHPStan has: 9 on PHPStan 1, 10 on PHPStan 2.
The level must be a whole number or 'max'. It can be written as an integer, a numeric string ('8' or '8.0') or a float (8.0), so env('SHIELDCI_PHPSTAN_LEVEL', 5) works. The analyzer checks the level before PHPStan starts. A fraction (8.9), any other string, or a level outside your PHPStan version's range (such as 10 on PHPStan 1) ends the analysis with an error that names the installed version and the levels it accepts.
ShieldCI Configuration
This analyzer runs in all environments. Customize which categories to enable and which paths to analyze:
Available Categories
You can enable/disable specific categories:
'categories' => [
'compile-errors', // Critical severity
'dead-code', // Medium severity
'deprecated-code', // High severity
'foreach-iterable', // High severity
'invalid-function-calls', // High severity
'invalid-imports', // Critical severity
'invalid-method-calls', // Critical severity
'invalid-method-overrides', // High severity
'invalid-offset-access', // High severity
'invalid-property-access', // High severity
'missing-model-relation', // High severity
'missing-return-statement', // High severity
'undefined-constant', // High severity
'undefined-variable', // High severity
'used-void-result', // High severity
'other', // Medium severity
],compile-errors, used-void-result and other stay on even when you pin a categories list that leaves them out. Only disabled_categories turns them off.
Disable Specific Categories
'disabled_categories' => [
'dead-code', // Temporarily ignore dead code
],Custom Paths
By default, PHPStan uses the global paths from config/shieldci.php:
'paths' => [
'analyze' => ['app', 'config', 'database', 'routes', 'resources/views'],
],Override only if needed - Specify PHPStan-specific paths:
'analyzers' => [
'reliability' => [
'enabled' => true,
'phpstan' => [
'paths' => ['app', 'routes'], // Only analyze these directories
],
],
],Why you might override:
- PHPStan is slower than other analyzers - limit to critical paths
- Some paths (like
config/) may have intentional dynamic code - Focus on application code (
app/) for faster feedback
References
- PHPStan Documentation
- PHPStan Rule Levels
- Larastan (Laravel-specific PHPStan)
- Laravel Type Safety Best Practices
Related Analyzers
- Composer Validation Analyzer - Ensures composer.json integrity
- Database Status Analyzer - Validates database connectivity
- Env File Analyzer - Checks environment configuration