pmjones/php-styler
PHP-Styler is a PHP 8.1+ code formatter that fully reformats your code for consistent spacing, indentation, and line lengths. It preserves logic and comments, is diff-friendly by default, and is customizable via styles, rules, and parses.
Installation:
composer require --dev pmjones/php-styler
Initialize Config:
./vendor/bin/php-styler init
This generates a php-styler.php file in your project root with default settings.
First Use Case: Preview formatting changes on a single file:
./vendor/bin/php-styler preview src/MyClass.php
php-styler.php (auto-generated by init).tests/Examples/ directory for styling patterns../vendor/bin/php-styler --help
Configure:
Extend the default php-styler.php with your preferred AFormat (e.g., DeclarationFormat for classes, Percs30Format for PER standards).
return new Config(
files: new Files(__DIR__ . '/src'),
format: new DeclarationFormat(lineLen: 120, indentLen: 2),
);
Integrate into CI/CD:
Add a check step to fail builds on formatting issues:
# .github/workflows/php.yml
- name: Check PHP Styler
run: ./vendor/bin/php-styler check
Pre-commit Hook:
Use apply to auto-format staged files:
# .git/hooks/pre-commit
#!/bin/sh
./vendor/bin/php-styler apply -- $(git diff --cached --name-only --diff-filter=ACM | grep '\.php$')
Team Alignment:
Use apply in a pre-merge hook to enforce consistency:
./vendor/bin/php-styler apply src/
git add src/
Diff-Friendly Changes:
Use diff to review changes before applying:
./vendor/bin/php-styler diff > styling-changes.diff
Parallel Processing:
Speed up large codebases with --workers:
./vendor/bin/php-styler apply --workers=auto
Custom Rules:
Override defaults in php-styler.php:
$format = new DeclarationFormat();
$format->styles['TFunction'] = ['blankLineBefore' => true];
IDE Support:
Configure your IDE (PHPStorm, VSCode) to trigger php-styler apply on save via settings.json or IDE plugins.
Example VSCode task:
{
"version": "2.0.0",
"tasks": [
{
"label": "Format PHP",
"type": "shell",
"command": "./vendor/bin/php-styler apply",
"problemMatcher": []
}
]
}
Monorepo Handling:
Use Files with multiple directories or Symfony Finder for granular control:
use Symfony\Component\Finder\Finder;
$finder = Finder::create()->files()->name('*.php')->in(['src', 'modules']);
return new Config(files: $finder, format: new PlainFormat());
Partial Formatting:
Exclude files/directories via Files:
return new Config(
files: new Files(__DIR__ . '/src', ['!tests/', '!vendor/']),
format: new DeclarationFormat(),
);
Comment Preservation:
/* ... */) are preserved in place but may shift vertically if surrounding code changes.//) stay on their original lines but may lose alignment.@php-styler-expansive for critical comments to force line breaks.String Literals:
@php-styler-expansive or manual line breaks:
$sql = <<<'SQL'
SELECT long_column_name AS "alias"
FROM very_long_table_name
SQL;
Horizontal Alignment:
// Before (aligned)
$foo = 'long' . $bar;
$foo = 'short' . $bar;
// After (unaligned)
$foo = 'long' . $bar;
$foo = 'short' . $bar;
PlainFormat with concatenationSpacing: false to retain alignment.Line Length Limits:
lineLen even after splitting (e.g., long URLs in strings), PHP-Styler will not truncate it.lineLen or refactor the code.Git Blame:
git blame. Mitigate by:
php-styler apply once..git-blame-ignore-revs.PHP 8.1+ Only:
composer require.Parse Failures:
Use the debug command to inspect problematic files:
./vendor/bin/php-styler debug src/BrokenFile.php
Cache Issues: Clear the cache if styles don’t update:
./vendor/bin/php-styler clear-cache
Verbose Output: Enable debug mode for detailed logs:
./vendor/bin/php-styler apply -vvv
Custom Formats:
Extend AFormat to create reusable styles:
class MyFormat extends DeclarationFormat {
public function __construct() {
$this->styles['TClass'] = ['blankLineBefore' => true];
$this->rules[] = new MyCustomRule();
}
}
Token Rules:
Add structural transformations by implementing IRule:
class AddSemicolons implements IRule {
public function apply(AToken $token, TokenStream $stream) {
if ($token instanceof TStatement && !$token->hasSemicolon()) {
$stream->insertAfter($token, new TSemicolon());
}
}
}
Parses (Token Replacements):
Override parseAs in your format to normalize syntax:
$format = new PlainFormat();
$format->parseAs['TDoubleColon'] = 'TDoubleColon::class'; // Normalize `::` to `::class`
Line Splitting:
Override split priorities in Splitter for domain-specific needs:
$format = new DeclarationFormat();
$format->splitter->splitPoints = [
'TArrowFunction' => 100, // Higher priority
'TComma' => 50,
];
Default Values:
PlainFormat uses lineLen: 88, indentLen: 4. Override explicitly to avoid surprises:
new PlainFormat(lineLen: 120, indentLen: 2)
Vendor Formats:
Pre-built formats (Percs30Format, SymfonyFormat) may conflict with team preferences. Audit their rules before adopting:
$format = new SymfonyFormat();
$format->rules = []; // Disable all rules
$format->styles['TFunction'] = ['blankLineBefore' => true]; // Customize
Case Sensitivity:
keywordCase in PlainFormat defaults to 'lower'. Set to 'upper' for ALL-CAPS keywords (e.g., IF instead of if).
How can I help you explore Laravel packages today?