fabpot/php-cs-fixer
Automatically fix PHP coding standards issues and unify style across your codebase. Includes rule sets like PER-CS, Symfony, and PhpCsFixer, plus configurable rules and migrations to modern PHP and PHPUnit. Supports PHP 7.4–8.5.
Installation
composer require --dev friendsofphp/php-cs-fixer
For dependency conflicts, use the shim:
composer require --dev php-cs-fixer/shim
Initialize Config Generate a project-specific config file:
./vendor/bin/php-cs-fixer init
This creates .php-cs-fixer.dist.php with a default rule set (e.g., @Symfony or @PhpCsFixer).
First Run
Fix all files in a directory (e.g., app/):
./vendor/bin/php-cs-fixer fix app/
Dry-run to preview changes:
./vendor/bin/php-cs-fixer check app/
fix on new PRs to enforce consistency.@autoPHPMigration to modernize PHP syntax (e.g., arrow functions, named arguments).@Symfony or @PSR12 for standardized style guides.CI Integration
Add to .github/workflows/php-cs-fixer.yml:
- name: PHP-CS-Fixer
run: ./vendor/bin/php-cs-fixer fix --dry-run --diff
Use --diff to show changes in PR comments.
Pre-Commit Hook
Use php-cs-fixer with robo.li or husky:
composer require --dev robo/robo
Add to robo.li:
$this->task('cs:fix')->run('./vendor/bin/php-cs-fixer fix');
Editor Integration
Artisan Command
Create a custom command (app/Console/Commands/FixCodeStyle.php):
use FriendsofPHP\PHPCSFixer\Runner\Runner;
use Symfony\Component\Console\Command\Command;
class FixCodeStyle extends Command {
protected function execute(InputInterface $input, OutputInterface $output) {
$runner = new Runner();
$runner->run(['fix' => 'app/']);
$output->writeln('Code style fixed!');
}
}
Register in app/Console/Kernel.php:
protected $commands = [
\App\Console\Commands\FixCodeStyle::class,
];
Git Hooks
Use php-cs-fixer in pre-commit:
git config --local core.hooksPath .githooks
Create .githooks/pre-commit:
#!/bin/sh
./vendor/bin/php-cs-fixer fix --dry-run --diff
Custom Rule Sets
Extend .php-cs-fixer.dist.php for Laravel-specific rules:
return PhpCsFixerConfig::create()
->setRules([
'@Symfony' => true,
'no_unused_imports' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'native_function_invocation' => ['include' => ['@all']],
'php_unit_test_class_requires_covers' => false, // Laravel-specific
]);
Rule Conflicts
@Symfony and @PSR12 may conflict (e.g., array_syntax).return PhpCsFixerConfig::create()
->setRules([
'@Symfony' => true,
'@PSR12' => true,
'array_syntax' => ['syntax' => 'short'], // Override
]);
Performance
fix.--parallel (PHP 7.4+) or exclude directories:
./vendor/bin/php-cs-fixer fix --parallel --exclude=vendor,storage
False Positives
no_unused_imports may flag Laravel facades.'no_unused_imports' => true,
'unused_imports' => 'none', // Disable for strict checks
PHP Version Mismatches
--allow-unsupported-php-version=yes (not recommended for production).Dry-Run with Diff
./vendor/bin/php-cs-fixer fix --dry-run --diff --path-mode=intersection
--path-mode=intersection: Only show files that would change.Rule-Specific Debugging Disable a rule to isolate issues:
./vendor/bin/php-cs-fixer fix --rules=@Symfony --exclude=ClassReferenceNameCasingFixer
Cache Issues Clear cache if rules behave unexpectedly:
./vendor/bin/php-cs-fixer clear-cache
Custom Rules
Create a rule (e.g., app/Rules/Custom/LaravelRule.php):
namespace App\Rules\Custom;
use PhpCsFixer\Fixer\FixerInterface;
use PhpCsFixer\Tokenizer\Tokens;
class LaravelRule implements FixerInterface {
public function isCandidate(Tokens $tokens) {
return true;
}
public function fix(Tokens $tokens) {
// Custom logic here
}
}
Register in config:
return PhpCsFixerConfig::create()
->withCustomFixers([new \App\Rules\Custom\LaravelRule()]);
Rule Sets
Save custom rule sets as files (e.g., rules/laravel.php):
return [
'no_unused_imports' => true,
'native_function_invocation' => ['include' => ['@all']],
];
Load in config:
->import(__DIR__.'/rules/laravel.php')
Parallel Processing
For monorepos, use --parallel with --path-mode=intersection to target specific paths:
./vendor/bin/php-cs-fixer fix --parallel --path-mode=intersection --path=packages/*
Facade Imports
Laravel facades (e.g., use Illuminate\Support\Facades\Log;) often trigger no_unused_imports.
Fix: Whitelist in config:
'no_unused_imports' => true,
'unused_imports' => 'none',
'import_fully_qualified' => false, // Allow facades
Dynamic Properties
Laravel’s dynamic properties (e.g., $this->foo = 'bar';) may conflict with no_unused_private_properties.
Fix: Exclude or adjust:
'no_unused_private_properties' => ['ignore_initialized_properties' => true],
Blade Templates PHP-CS-Fixer ignores Blade files by default. To include them:
./vendor/bin/php-cs-fixer fix --path=resources/views --rules=@Symfony
Migration Files Migrations often use raw SQL or dynamic code. Exclude them:
->exclude([
'database/migrations/*',
'vendor/*',
])
How can I help you explore Laravel packages today?