repinspl / php-cs-fixer-html-indent
PHP-CS-Fixer custom fixers that preserve HTML-context indentation in mixed PHP/HTML files
Package info
github.com/RepinsPL/php-cs-fixer-html-indent
pkg:composer/repinspl/php-cs-fixer-html-indent
Requires
- php: >=8.0
- friendsofphp/php-cs-fixer: ^3.0
Requires (Dev)
- phpunit/phpunit: ^10.5 || ^11.0
README
Custom fixers for PHP-CS-Fixer that preserve indentation of PHP blocks embedded in HTML/Blade files.
The problem
PHP-CS-Fixer formats PHP blocks without considering the surrounding HTML context. In mixed files (e.g. Blade templates) this breaks the indentation:
Before running php-cs-fixer — correct indentation within the HTML context:
<div> <main> <?php $users = DB::table('users') ->where('active', true) ->get(); foreach ($users as $user) { echo $user->name; } ?> </main> </div>
After running php-cs-fixer — HTML context indentation is lost:
<div> <main> <?php $users = DB::table('users') ->where('active', true) ->get(); foreach ($users as $user) { echo $user->name; } ?> </main> </div>
With this library — php-cs-fixer formats the PHP while the HTML indentation is preserved:
<div> <main> <?php $users = DB::table('users') ->where('active', true) ->get(); foreach ($users as $user) { echo $user->name; } ?> </main> </div>
Installation
composer require --dev repinspl/php-cs-fixer-html-indent
Configuration
Register both fixers and enable their rules in your .php-cs-fixer.dist.php:
<?php $fixers = [ new \RepinsPL\PhpCsFixerHtmlIndent\HtmlContextDedentFixer(), new \RepinsPL\PhpCsFixerHtmlIndent\HtmlContextReindentFixer(), ]; return (new PhpCsFixer\Config()) ->registerCustomFixers($fixers) ->setRules([ // Your other rules... 'RepinsPL/html_context_dedent' => true, 'RepinsPL/html_context_reindent' => true, ]) ->setFinder( PhpCsFixer\Finder::create() ->in(__DIR__) );
Important: Both fixers must be enabled together. Dedent without reindent will strip the indentation without restoring it.
How it works
The library provides two fixers that wrap the entire PHP-CS-Fixer pipeline:
| Fixer | Priority | Role |
|---|---|---|
RepinsPL/html_context_dedent |
1000 |
Before other fixers — strips base HTML indentation from PHP blocks |
RepinsPL/html_context_reindent |
-1000 |
After all fixers — restores base HTML indentation |
This allows other fixers (e.g. braces, indentation_type) to work on PHP code without extra indentation and format it correctly. Once formatting is complete, the HTML context indentation is restored.
Both tab-based and space-based indentation are supported. The base indentation style is detected automatically from the HTML context surrounding each PHP block.
Contributing
If you find a case where the fixers produce incorrect indentation, please open an issue with a minimal PHP/HTML snippet that demonstrates the problem. This helps us write a test and fix the bug.
Requirements
- PHP >= 8.0
- PHP-CS-Fixer ^3.0