fabpot/php-cs-fixer
PHP CS Fixer is a command-line tool for automatically fixing PHP coding standards issues. It formats and modernizes code using configurable rulesets, supports custom rule configurations, and helps keep projects consistent and clean across teams and CI.
Installation Add the package via Composer:
composer require --dev fabpot/php-cs-fixer
Initialize the default config (optional but recommended):
vendor/bin/php-cs-fixer fix --config=vendor/fabpot/php-cs-fixer.php.dist --dry-run
First Use Case Run a dry-run on a single file to verify behavior:
vendor/bin/php-cs-fixer fix app/Http/Controllers/ExampleController.php --dry-run
Check the output for changes without modifying files.
Where to Look First
vendor/fabpot/php-cs-fixer.php.dist (PSR12 by default).vendor/bin/php-cs-fixer --help for available rules and options.Pre-Commit Hook
Integrate with Git hooks (e.g., pre-commit) to auto-fix files before commits:
vendor/bin/php-cs-fixer fix --dry-run --diff --allow-risky=yes
--diff to show changes in Git diff format.--allow-risky=yes skips potentially unsafe fixes (e.g., modifying class constants).CI Pipeline Run in CI to enforce standards (fail build if fixes are needed):
vendor/bin/php-cs-fixer fix --level=psr12 --dry-run --diff --stop-on-failure
--stop-on-failure exits with non-zero if fixes are required.--level=psr12 enforces PSR12 rules (adjust as needed).Custom Config
Extend the default config in .php-cs-fixer.dist.php:
<?php
return PhpCsFixer\Config::create()
->setRules([
'@PSR12' => true,
'no_unused_imports' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'phpdoc_align' => false, // Disable if not needed
])
->setRiskyAllowed(true)
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__.'/app')
->exclude('app/Helpers')
);
setRules(): Override or add rules (use @Symfony presets for framework-specific rules).setFinder(): Target specific directories/files (exclude tests, helpers, etc.).setRiskyAllowed(): Enable/disable risky fixes globally.Incremental Fixing
Use --path-mode=diff to only fix changed files in a PR:
vendor/bin/php-cs-fixer fix --path-mode=diff --diff
return PhpCsFixer\Config::create()
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true, // Enable risky Symfony rules
'no_unused_imports' => true,
]);
--parallel:
vendor/bin/php-cs-fixer fix --parallel
Risky Fixes
class_definition, final_class) can break functionality.--allow-risky=yes cautiously or disable risky rules:
->setRiskyAllowed(false)
->setRules(['@Symfony:risky' => false])
Performance
--path-mode=diff in CI to only check changed files.php-cs-fixer cache:clear if rules change frequently.Config Conflicts
.php-cs-fixer.dist.php from multiple sources can cause conflicts.php-cs-fixer config:dump to generate a fresh config:
vendor/bin/php-cs-fixer config:dump --standard=PSR12 > .php-cs-fixer.dist.php
False Positives
no_unused_imports may flag Laravel-specific imports (e.g., use Illuminate\Support\Facades\Route;).->setFinder(PhpCsFixer\Finder::create()->exclude('app/Providers'))
Line Endings
\n vs \r\n), causing Git noise.--line-ending=unix or configure Git to handle line endings.--dry-run first to preview changes:
vendor/bin/php-cs-fixer fix --dry-run --diff
vendor/bin/php-cs-fixer fix -v
--rules:
vendor/bin/php-cs-fixer fix --rules=ordered_imports --diff
Custom Rules
Extend PHP-CS-Fixer with custom rules by creating a RuleSet class:
// CustomRule.php
use PhpCsFixer\Fixer\FixerInterface;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\Tokenizer\Tokens;
class CustomRule implements FixerInterface, ConfigurableFixerInterface {
public function isCandidate(Tokens $tokens) { /* ... */ }
public function isRisky() { return false; }
public function fix(PhpCsFixer\Tokenizer\Tokens $tokens) { /* ... */ }
public function getConfiguration() { return []; }
}
Register it in your config:
->registerCustomFixers([__DIR__.'/CustomRule.php'])
Parallel Processing For custom rules, ensure thread safety by avoiding static state.
Integration with Laravel Artisan Create a custom Artisan command for team-wide usage:
php artisan make:command FixCs
Example:
// app/Console/Commands/FixCs.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Process\Process;
class FixCs extends Command {
protected $signature = 'fix:cs {--dry-run}';
protected $description = 'Run PHP-CS-Fixer';
public function handle() {
$process = new Process(['vendor/bin/php-cs-fixer', 'fix', $this->option('dry-run') ? '--dry-run' : null]);
$process->run();
$this->output->write($process->getOutput());
if (!$process->isSuccessful()) exit(1);
}
}
Run with:
php artisan fix:cs --dry-run
@PSR12, @Symfony) can be overridden partially:
->setRules([
'@PSR12' => true,
'no_unused_imports' => false, // Disable only this rule
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__)
->exclude(['vendor', 'storage', 'tests', '*.blade.php'])
)
vendor/bin/php-cs-fixer cache:clear
How can I help you explore Laravel packages today?