Installation:
composer require --dev innmind/static-analysis
This installs a curated set of static analysis tools (primarily Psalm) and their dependencies.
First Configuration:
Create psalm.xml in your project root with the provided template. Key settings:
errorLevel="1": Enforces strict type-checking (treat warnings as errors).resolveFromConfigFile="true": Ensures Psalm respects your project’s composer.json autoload paths.findUnusedBaselineEntry="true": Helps identify outdated baseline entries.First Run:
vendor/bin/psalm --init
Generates a baseline file (psalm-baseline.xml) to suppress known issues (e.g., third-party type mismatches).
Initial Analysis:
vendor/bin/psalm
Run this in CI/CD or pre-commit hooks to catch type errors early.
Pre-Commit Hooks:
Use psalm in a Git hook to block type errors before merging:
composer require --dev laravel/pint # Optional: Auto-format code
composer require --dev dealerdirect/phpcodesniffer-composer-installer
Example .git/hooks/pre-commit:
#!/bin/sh
vendor/bin/psalm --no-cache --no-progress --output-format=github
if [ $? -ne 0 ]; then
echo "Psalm found errors. Fix them before committing."
exit 1
fi
CI/CD Pipeline:
Add to Laravel’s .github/workflows/laravel.yml:
- name: Static Analysis
run: vendor/bin/psalm --init && vendor/bin/psalm --no-cache
IDE Integration: Configure PHPStorm to use Psalm:
vendor/bin/psalm as the executable in Settings > Languages & Frameworks > PHP > Static Analysis.Ignoring Framework Files:
Extend psalm.xml to exclude Laravel’s core (if using custom types):
<ignoreFiles>
<directory name="vendor/laravel/framework" />
<directory name="vendor/laravel/tinker" />
</ignoreFiles>
Custom Types for Laravel:
Create a psalm-plugin.xml to define missing types (e.g., for Illuminate\Support\Collection):
<psalm>
<pluginClass>Innmind\StaticAnalysis\PsalmPlugin</pluginClass>
<layer>
<whitelist>
<namespace>Illuminate\Support</namespace>
</whitelist>
</layer>
</psalm>
Testing Integration:
Use Psalm’s --test-report to validate test coverage:
vendor/bin/psalm --test-report=psalm-test-report.xml
Baseline Bloat:
psalm-baseline.xml grows with every run, slowing analysis.vendor/bin/psalm --find-unused-baseline-entries
False Positives in Laravel:
Collection::when()).@mixin in stub files or suppress with:
// @psalm-suppress MixedReturnType
Configuration Overrides:
psalm.xml overrides may conflict with team settings.psalm --config=path/to/config.xml to enforce consistency.Verbose Output:
Run with --verbose to diagnose configuration issues:
vendor/bin/psalm --verbose --no-cache
Isolated Analysis:
Test changes incrementally with --files:
vendor/bin/psalm --files=src/Http/Controllers/
Plugin Conflicts:
innmind/static-analysis alongside other Psalm plugins (e.g., vimeo/psalm), ensure no duplicate registrations in psalm.xml.Custom Rules: Extend Psalm’s rules by creating a plugin:
// app/Psalm/Plugin.php
namespace App\Psalm;
use Psalm\Plugin\PluginEntryPointInterface;
use Psalm\Plugin\RegistrationInterface;
class Plugin implements PluginEntryPointInterface {
public function register(RegistrationInterface $registration): void {
$registration->addConfigurationDefinition(
'custom_rule',
\Psalm\Config\ConfigurationDefinition::create()
->setType('bool')
->setDefaultValue(false)
);
}
}
Register in psalm.xml:
<pluginClass>App\Psalm\Plugin</pluginClass>
Type Coverage:
Use psalm --stats to track type coverage and prioritize fixes:
vendor/bin/psalm --stats --output-format=text
Performance:
Cache results in CI with --cache-dir=.psalm-cache and clear periodically:
vendor/bin/psalm --cache-dir=.psalm-cache --no-cache
How can I help you explore Laravel packages today?