pmjones/php-styler
PHP-Styler is a PHP code formatter that tokenizes source files and rebuilds them with consistent spacing, indentation, and automatic line splitting. Configurable Styles, Rules, and Parses customize the diff-friendly output, while logic and comments are preserved. No dependencies beyond PHP 8.1.
Architecture fit. PHP-Styler is a standalone CLI formatter with no framework coupling — it consumes .php paths and writes text back. Integration into a Laravel codebase is therefore a tooling decision, not an application-architecture one. It requires PHP 8.4 (raised in 0.17.0), which is acceptable as a require-dev dependency only if CI and developer machines standardize on 8.4 while the deployable runtime may remain on 8.2/8.3. The package is self-hosting (composer cs-check runs the tool on its own source), which is a meaningful dogfooding signal.
Integration feasibility. Mechanically trivial: composer require --dev, php-styler init, then preview / diff / check / apply. The command surface maps cleanly onto CI (check returns exit 1 on drift) and onto pre-commit hooks. The genuine capability gap versus the incumbent (Laravel Pint / PHP CS Fixer) is automatic line splitting — prioritized split points (attributes → arrow fns → commas → operators → fluent calls) that reflow over-long statements. Pint normalizes spacing and ordering but does not reflow lines. That is the only defensible reason to spend evaluation time here.
Technical risk. High, and concentrated in three places:
apply discards all existing formatting by design. On an active repository this produces a repo-wide commit that invalidates every open branch and in-flight PR.Files helper recurses directories for .php, which will sweep .blade.php templates, bootstrap/cache, and any vendored PHP. Blade files tokenized as PHP are a corruption vector, not a style regression.Key questions to resolve before committing:
apply produce a zero-byte diff?Files (or a Symfony Finder replacement) reliably exclude *.blade.php, vendor/, storage/, bootstrap/cache/?Percs30Format actually PER 3.0-conformant, and how far does it diverge from Laravel's Pint preset?cache parameter appears in the Config signature) and does it survive branch switches?Stack fit. Complementary to, not a replacement for, Pint — but the two cannot both own formatting. Pick one as the enforcement gate. Realistic positioning: keep Pint as the enforced standard, and evaluate PHP-Styler as a long-line reflow pass using PlainFormat with structural rules disabled, so the only change it makes is line splitting. That isolates the one capability we lack and keeps the diff reviewable.
Migration path. Three-phase, gated:
php-styler preview and php-styler diff across a single low-churn package. Confirm idempotency, inspect the split-line output by hand, confirm the test suite still passes after a scratch-branch apply, and confirm git diff -w behaves as expected (PlainFormat with no rules should be whitespace-only; DeclarationFormat / vendor formats also reorder imports, normalize trailing commas, collapse empty bodies, and change keyword case, so those require a full test + PHPStan pass rather than a whitespace check).php-styler check to CI as a non-blocking job for 2–4 weeks to measure drift volume and iteration cost..git-blame-ignore-revs, and only then make check blocking.Compatibility. Pin an exact version (0.17.x), not a range — a 0.x package with a rewrite history will break on minor bumps. Exclude Blade templates, generated files, and vendor/ explicitly in the config. Confirm the CI runner image ships PHP 8.4 before scheduling the pilot; if not, that alone may defer the evaluation.
Sequencing. Exclusions and config → preview/diff review → idempotency and test-suite verification → shadow CI → freeze-and-apply → blame-ignore file → blocking gate. Do not run the initial apply on main while feature branches are open.
Maintenance. Low code footprint on our side (one config file, one CI step), but the dependency itself is a maintenance liability: pre-1.0, single maintainer, and a demonstrated willingness to rewrite. Budget for re-reading an upgrade guide on each minor bump. The customization surface (styles, rules, parseAs arrays on a Format) is declarative and small — roughly a dozen composable rules — so team ramp-up is measured in hours, not days.
Support. No commercial backing, no SLA, no dependents to indicate community depth. Escalation path is upstream GitHub issues. Mitigation: keep the tool strictly in dev/CI — never a runtime dependency — so a broken release blocks formatting, not deploys. Our own php-styler.php and CI step are the only artifacts to remove if we abandon it.
Scaling. Adequate: --workers=N / --workers=auto uses proc_open with no extra extensions, and the sequential path auto-engages below 8 files. Runtime on a mid-size Laravel app should be CI-tolerant; validate on our largest package rather than assuming. The 0.17.0 removal of nikic/php-parser in favor of native PhpToken meaningfully reduced the dependency and startup cost.
Failure modes to monitor.
apply on a full test + static-analysis pass.apply the code is canonical and the docblocks are legacy. Expect a follow-up cleanup pass.= and . columns) will be flattened. Teams that value aligned assignments should be told up front.Ramp-up. One engineer for the pilot; the broader team needs only the config location, the four commands, and the rule that nobody hand-formats against the tool. Total investment to a go/no-go decision: roughly 2–3 engineer-days. Given 42 stars, zero dependents, and a pre-1.0 rewrite history, the defensible recommendation is a timeboxed spike scoped to long-line reflow, retaining Pint as the enforced house style unless the reflow output proves clean enough to justify the churn.
How can I help you explore Laravel packages today?