Чому я взагалі повернулася до formatter-ів
Це не була ситуація, де мені терміново знадобився новий formatter. Laravel Pint уже давно був у require-dev, але фактично я його ніколи не використовувала.
Реальний formatting workflow проєкту був побудований навколо friendsofphp/php-cs-fixer: окремий .php-cs-fixer.dist.php, пакет із custom fixers і перевірка PHP-CS-Fixer у CI.
Коли я вкотре переглядала tooling проєкту, то помітила цю невідповідність: Pint уже є серед залежностей, але вся реальна робота виконується іншим formatter-ом. Тоді я й вирішила перевірити, чи справді PHP-CS-Fixer дає мені щось, чого не може покрити Pint, і тільки після цього прибирати старий механізм.
Спочатку я перевірила, що саме робив PHP-CS-Fixer
<?php $finder = (new PhpCsFixer\Finder()) ->in(__DIR__) ->exclude(['bootstrap', 'storage', 'public', 'node_modules', 'vendor']); return (new PhpCsFixer\Config()) ->registerCustomFixers(new PhpCsFixerCustomFixers\Fixers()) ->setRules([ '@PSR12' => true, '@PHP81Migration' => true, PhpCsFixerCustomFixers\Fixer\ConstructorEmptyBracesFixer::name() => true, PhpCsFixerCustomFixers\Fixer\NoUselessCommentFixer::name() => true, PhpCsFixerCustomFixers\Fixer\PhpdocNoIncorrectVarAnnotationFixer::name() => true, 'binary_operator_spaces' => [ 'default' => 'single_space', 'operators' => [ '=' => 'single_space', '=>' => 'single_space', ], ], 'not_operator_with_successor_space' => true, 'cast_spaces' => true, 'array_syntax' => ['syntax' => 'short'], 'phpdoc_scalar' => true, 'phpdoc_align' => [ 'align' => 'left', ], ]) ->setFinder($finder);Я не хотіла просто видалити цей config і сподіватися, що Pint зробить приблизно те саме. Спочатку я розібрала правила й порівняла їх із Laravel preset у Pint.
Звичайні style rules на кшталт spacing, short array syntax, casts і PHPDoc formatting окремо переносити не було сенсу, якщо потрібна поведінка вже покривається Pint.
Але серед старих правил були й такі, які я не хотіла автоматично переносити. Наприклад, @PHP81Migration - це вже не просто форматування, а migration ruleset, який може трансформувати код.
Так само я не стала переносити custom fixers, що змінюють або видаляють comments і PHPDoc content. Я вирішила чіткіше розділити відповідальність: formatter форматує код, а змістовний cleanup коду та документації залишається окремою задачею.
Що було в PHP-CS-Fixer | Що я вирішила |
|---|---|
Звичайні style rules | Не дублювати, якщо потрібний стиль уже покриває Pint |
@PHP81Migration | Не переносити в formatter config |
Constructor formatting | Залишити стандартне форматування Pint |
Comment/PHPDoc custom fixers | Не переносити як formatting rules |
Окремий Finder scope | Не відтворювати механічно, а використовувати нормальний scope Pint |
Окремий Finder scope | Видалити після завершення audit |
Окремо я не переносила старий Finder один в один. У PHP-CS-Fixer, наприклад, був виключений `bootstrap`, але під час переходу я навмисно прогнала Pint по його нормальному project scope і привела до одного стилю також PHP-файли в `bootstrap`.
Після audit я вирішила залишити тільки Laravel Pint
Після порівняння я не знайшла причини продовжувати підтримувати окремий PHP-CS-Fixer workflow.
Pint уже був залежністю проєкту, Laravel preset покривав потрібний мені базовий code style, а специфічні правила старого formatter-а або вже не потребували окремої конфігурації, або взагалі не належали до formatting.
Тому замість підтримки двох інструментів я вирішила зробити Pint єдиним formatter-ом для PHP-коду.
Конфігурація Pint вийшла дуже маленькою
{ "preset": "laravel"}Спочатку такий `pint.json` навіть виглядав підозріло простим після великого PHP-CS-Fixer config. Але саме цього я й хотіла: почати зі стандартного Laravel preset і додавати overrides тільки тоді, коли в проєкті справді з’явиться конкретна причина.
Тоді я прибрала PHP-CS-Fixer з проєкту
PHP-CS-Fixer - фактичний formatter
.php-cs-fixer.dist.php
php-cs-fixer-custom-fixers
PHP-CS-Fixer check у CI
Laravel Pint у require-dev, але не використовується
Laravel Pint - єдиний formatter
pint.json
composer format
composer format:check
Pint check у CI
PHP-CS-Fixer dependencies і config видалені
З composer.json я прибрала прямі залежності friendsofphp/php-cs-fixer і kubawerlos/php-cs-fixer-custom-fixers. Разом із ними Composer прибрав і транзитивні пакети, потрібні тільки старому tooling.
Після цього я видалила .php-cs-fixer.dist.php, старий cache і його entries у .gitignore.
Також я пройшлася по README, deployment documentation і GitLab CI, тому що не хотіла залишити ситуацію, де локально вже використовується Pint, а в документації чи pipeline все ще живе стара команда PHP-CS-Fixer.
Для мене CI тут важливий саме як продовження локального workflow: та сама перевірка має виконуватися автоматично в pipeline. Про те, як я сприймаю сам CI/CD flow і чим для мене відрізнялося його представлення в Bitbucket та GitLab, я писала окремо в порівнянні Bitbucket CI Bot і GitLab Pipeline.
{ "scripts": { "format": "pint", "format:check": "pint --test" }}Я спеціально винесла команди в Composer scripts, щоб не пам’ятати точний шлях до binary і використовувати однаковий interface локально та в CI.
pint: extends: .php_job stage: quality script: - composer format:checkПерший реальний запуск Pint показав 244 style issues
До цього моменту Pint був у проєкті лише як dependency. Тепер я вперше використала його як реальний formatter і спочатку запустила check без автоматичних змін.
composer format:check
Pint перевірив 801 PHP-файл і знайшов 244 style issues. Це добре показало різницю між стилем, який роками підтримував PHP-CS-Fixer, і baseline, який задає Laravel Pint.
Я вирішила одразу привести весь PHP-код до одного baseline
composer format
Через project-wide formatting diff вийшов великим: у підсумку змінилося 252 файли.
Це було очікувано. Окрім видалення старого tooling і оновлення конфігурації, Pint переформатував PHP-код у app, database, routes, config, bootstrap і tests.
Саме тому я винесла цю роботу в окрему задачу. Великий formatting diff набагато легше перевіряти, коли в ньому немає паралельно нової функціональності або business logic changes.
Після форматування я перевірила не тільки Pint
Оскільки formatter змінив велику кількість PHP-файлів, для мене було важливо переконатися, що migration залишилася саме formatting change.
Після форматування composer format:check проходив чисто, PHPStan не знаходив помилок, а Unit, Integration і Feature test suites також завершувалися успішно.
Тільки після цього я вважала migration завершеною.
Тепер у мене один зрозумілий formatting workflow
composer format composer format:check`composer format` я використовую, коли хочу автоматично привести код до потрібного стилю. `composer format:check` нічого не змінює і просто перевіряє стан codebase, тому саме він використовується в CI.
Що я залишила для себе після цього cleanup
Якщо dependency є в composer.json, це ще не означає, що проєкт реально нею користується.
Перед видаленням старого tooling варто спочатку розібрати його config.
Не потрібно переносити кожне старе правило в новий formatter автоматично.
Migration rules і cleanup comments не обов’язково мають бути частиною formatter-а.
Один formatter, одна локальна команда і одна CI-перевірка значно простіші в підтримці.
Великий project-wide formatting краще робити окремою задачею без функціональних змін.
У підсумку я не замінила один formatter іншим з нуля. Laravel Pint уже був у проєкті, просто до цього я ним не користувалася. Я перевірила старий PHP-CS-Fixer config, залишила тільки те, що справді мало сенс, прибрала зайвий tooling і зробила Pint єдиним механізмом форматування PHP-коду.



