PHPCBF: fix style automatically
| Install | |
| Simple auto-fix | |
| Multi-line calls | |
| Prove zero change | |
| [x] versus [ ] | |
| When not to auto-fix |
Install
PHPCBF arrives together with PHPCS: same Composer package, same PHAR download, same Docker image. Where phpcs only reports, phpcbf rewrites the file:
composer require --dev phpcsstandards/php_codesniffer vendor/bin/phpcbf --version
Simple auto-fix
The demo file from the previous article reported 12 errors. Ten of them carry the [x] mark — spacing, lowercase constants, header block, trailing whitespace:
phpcbf --standard=PSR12 bad.php
A TOTAL OF 10 ERRORS WERE FIXED IN 1 FILE
Re-checking shows only the two findings without the mark left: they need a human (a namespace and a camelCase rename).
Multi-line calls
Harder-looking reports fix just as mechanically. A legacy page template reported 81 errors of one family: several arguments sharing one line, and the closing parenthesis not on a line by itself:
<?php
$result .= ao_card(
'ru', 'edu/literature/witcher/', '/literature/witcher_card',
'Witcher ...', 'Witcher',
'Fan art', 'Book order. Characters.',
'default_icon.png', 'reg', 'png'
)
;
ERROR | [x] Only one argument is allowed per line in a multi-line function call
ERROR | [x] Closing parenthesis of a multi-line function call must be on a line by itself
Fixed on a copy, limited to that sniff family so nothing else moves:
phpcbf --standard=PSR12 --sniffs=PSR2.Methods.FunctionCallSignature Page.php
A TOTAL OF 81 ERRORS WERE FIXED IN 1 FILE
Every call became one-argument-per-line with the bracket on its own line:
$result .= ao_card(
'ru',
'edu/literature/witcher/',
'/literature/witcher_card',
...
'png'
)
Prove zero change
Three checks, cheapest first. Syntax gate:
php -l Page.php
No syntax errors detected in Page.php
Plain diff shows 164 changed lines — all whitespace, but "all" is a claim. Make it a fact: compare token streams with whitespace and comments stripped. PHP executes tokens, so identical streams mean identical behaviour:
$t = token_get_all($code);
// drop T_WHITESPACE, T_COMMENT, T_DOC_COMMENT, compare the rest
tokens before=2597 after=2597
IDENTICAL: semantics unchanged
2597 tokens before, 2597 after, in the same order. The fixer moved only brackets and newlines — a runtime regression is not possible here.
[x] versus [ ]
The mark decides the workflow. [x] is safe for the machine: spacing, casing of constants, header blocks, trailing whitespace, bracket placement. [ ] is always yours: camelCase renames (every caller must change too), argument order constraints, files mixing declarations with executable code.
phpcs --report=full file.php | grep -c "\[x\]"
When not to auto-fix
- Huge diffs on stable legacy files: the fix is safe but nobody can review 164 changed lines with confidence — fix new code first.
- Files kept byte-identical on purpose: if two copies of a template are compared byte for byte, reformatting one desyncs them. Fix the copies together or not at all.
- Mixed findings: run the safe sniff families first (--sniffs=... limits the run), keep reformatting away from logic changes in the same commit.
Always re-run phpcs after phpcbf, review with git diff, and prove behaviour with the token comparison above whenever the diff is too large to read.
Article author: Andrei Olegovich
| Development with PHP | |
| PHP linters we use | |
| php -l and lint-php.sh | |
| PHPCS: PHP CodeSniffer | |
| phpcs.xml ruleset file | |
| PHPCBF: fix style automatically | |
| wrap-long-lines.sh | |
| PHPStan and Psalm |