slam/php-cs-fixer-extensions
Extensions and ready-to-use rulesets for FriendsOfPHP PHP-CS-Fixer. Adds custom fixers like final_abstract_public, final_internal_class, utf8 cleanup, inline comment spacing, function reference spacing, and PHP-only proxy fixers for consistent code style.
Installation: Add the package to your project via Composer:
composer require --dev slam/php-cs-fixer-extensions
Configure:
Create or update your .php_cs file in the project root. Start with the basic example from the README and adjust paths/rules as needed:
<?php
$config = new PhpCsFixer\Config();
$config->setRiskyAllowed(true);
$config->registerCustomFixers([
new SlamCsFixer\FinalAbstractPublicFixer(),
new SlamCsFixer\FinalInternalClassFixer(),
new SlamCsFixer\FunctionReferenceSpaceFixer(),
new SlamCsFixer\InlineCommentSpacerFixer(),
new SlamCsFixer\PhpFileOnlyProxyFixer(new PhpCsFixer\Fixer\Basic\BracesFixer()),
new SlamCsFixer\Utf8Fixer(),
]);
$config->setRules([
'Slam/final_abstract_public' => true,
'Slam/final_internal_class' => true,
'Slam/function_reference_space' => true,
'Slam/inline_comment_spacer' => true,
'Slam/php_only_braces' => true,
'Slam/utf8' => true,
]);
$config->getFinder()
->in(__DIR__ . '/app')
->in(__DIR__ . '/tests')
->name('*.php')
->name('*.phtml');
return $config;
First Use Case: Run PHP-CS-Fixer to auto-fix your codebase:
vendor/bin/php-cs-fixer fix
Focus on the Utf8Fixer and final_abstract_public rules first, as they address common Laravel pain points (encoding issues and abstract class misuse).
CI/CD Pipeline: Add a step to run PHP-CS-Fixer with this extension in your CI (e.g., GitHub Actions):
- name: Run PHP-CS-Fixer
run: vendor/bin/php-cs-fixer fix --diff --dry-run
Use --diff to show changes and --dry-run to fail if fixes are needed.
Pre-Commit Hooks: Use tools like Husky or Laravel Pint to run PHP-CS-Fixer locally:
composer require --dev laravel/pint
./vendor/bin/pint --test
Team Onboarding:
CONTRIBUTING.md.php-cs-fixer section in your team’s style guide with examples of fixed vs. non-compliant code.| Rule | Use Case | Laravel-Specific Example |
|---|---|---|
final_abstract_public |
Enforce final on abstract public methods to prevent subclass overrides. |
Abstract repositories where methods should not be overridden in child classes. |
final_internal_class |
Mark internal classes as final to avoid accidental inheritance. |
Service container classes or internal utilities. |
function_reference_space |
Standardize spacing around function calls. | User::find() vs. User ::find() in Blade templates. |
inline_comment_spacer |
Improve readability of inline comments. | // $user->name → // $user->name (with trailing space). |
php_only_braces |
Apply braces rules to PHP files only (avoid PHTML conflicts). | { vs. } in *.php files vs. Blade templates. |
utf8 |
Enforce UTF-8 encoding in all files. | Blade templates with non-UTF-8 characters (e.g., é, ñ). |
Blade/PHTML Files:
Use the PhpFileOnlyProxyFixer to apply braces rules to *.php files while excluding Blade templates:
$config->registerCustomFixers([
new SlamCsFixer\PhpFileOnlyProxyFixer(new PhpCsFixer\Fixer\Basic\BracesFixer()),
]);
Doctrine Entities:
Exclude Doctrine entities from final_internal_class if they use attributes (e.g., @ORM\Entity):
$config->getFinder()
->exclude('app/Entities');
PHPUnit Tests: Add test directories to the finder:
$config->getFinder()
->in(__DIR__ . '/tests/Unit')
->in(__DIR__ . '/tests/Feature');
setRiskyAllowed(true):
$config->setRules([
'Slam/final_abstract_public' => false, // Disable if risky
]);
UTF-8 Encoding Issues:
Utf8Fixer may fail on files with mixed encodings (e.g., UTF-8 BOM or ISO-8859-1).iconv:
iconv -f ISO-8859-1 -t UTF-8 file.php > temp && mv temp file.php
Doctrine Attribute Conflicts:
FinalInternalClassFixer may flag Doctrine entities with @ORM\* attributes as "internal."PHP 8.5+ Features:
readonly class support) may not work on older PHP versions.php-cs-fixer’s --version flag to check compatibility:
vendor/bin/php-cs-fixer --version
Dry Runs:
Always use --dry-run to preview changes:
vendor/bin/php-cs-fixer fix --dry-run --diff
Rule-Specific Debugging:
vendor/bin/php-cs-fixer fix --rules=Slam/utf8 --dry-run
--verbose for detailed output:
vendor/bin/php-cs-fixer fix --verbose
Custom Fixers:
FinalAbstractPublicFixer to exclude certain classes:
class CustomFinalAbstractPublicFixer extends SlamCsFixer\FinalAbstractPublicFixer {
protected function isRisky(): bool {
return false; // Disable risky behavior
}
}
Finder Exclusions:
->exclude() to skip directories (e.g., vendor/, node_modules/):
$config->getFinder()->exclude('vendor');
Rule Priorities:
Utf8Fixer before other rules to avoid encoding-related errors:
$config->setRules([
'Slam/utf8' => true,
'Slam/final_abstract_public' => true,
]);
Caching:
$config->setCacheFile(__DIR__ . '/.php_cs_fixer.cache');
Custom Fixers:
SlamCsFixer\AbstractFixer. Example:
namespace App\CsFixer;
use PhpCsFixer\Fixer\FixerInterface;
use PhpCsFixer\Tokenizer\Tokens;
class LaravelUseStatementFixer implements FixerInterface {
public function isRisky(): bool { return false; }
public function getName() { return 'Laravel_use_statement'; }
public function getDescription() { return 'Fix Laravel-specific use statements'; }
public function fix(Tokens $tokens) { /* ... */ }
}
Rule Sets:
laravel, tests):
$config->importRulesFromFile(__DIR__ . '/rules/laravel.php');
CI/CD Integration:
How can I help you explore Laravel packages today?