Внедрение PHP-CS-Fixer в легаси PHP-проекты
Вы работаете над унаследованным legacy PHP-проектом и хотите использовать friendsofphp/php-cs-fixer для обеспечения согласованного стандарта кодирования. Но вы не знаете, как это сделать, не вызывая проблем.
Какой может быть стратегия внедрения PHP-CS-Fixer в ваш легаси PHP-проект, которая снижает риски и приглашает других разработчиков к сотрудничеству?
Требования
Если вы хотите, чтобы внедрение PHP-CS-Fixer в ваш легаси PHP-проект прошло успешно, должны выполняться следующие требования:
- Вы должны использовать PHP-CS-Fixer в вашей системе непрерывной интеграции. Когда вы коммитите и пушите код, который не соответствует вашим стандартам кодирования, необходимо, чтобы сборка в вашей системе непрерывной интеграции не удалась.
- Вы должны запускать PHP-CS-Fixer в своей среде разработки. Когда вы изменяете PHP код и тот код, который не соответствует вашим стандартам кодирования, должен исправляться PHP-CS-Fixer, исправляя все нарушения стандартов кодирования. Вам не нужно получать сообщения о нарушении стандартов кодирования в среде разработки; код должен сразу исправляться. Нужна простая команда запуска PHP-CS-Fixer в среде разработки, чтобы её можно было часто запускать.
- Необходимо, чтобы PHP-CS-Fixer применял исправления совместимые с версией PHP, которую вы используете в рабочей среде. Если ваш проект работаете на PHP 5.3, вы не захотите, чтобы PHP-CS-Fixer применял исправления, требующиеся для PHP 8.1.
Установка PHP-CS-Fixer
Вы можете установить PHP-CS-Fixer с помощью composer, phive или загрузив PHAR со страницы релизов. Но вы можете подробно изучить варианты установки и инструкции PHP-CS-Fixer в README.md проекта. Я не буду повторять их.
Я рекомендую использовать composer для установки PHP-CS-Fixer, чтобы вы могли получать автоматические обновления зависимостей от Dependabot, Renovatebot или подобных сервисов. Если вы устанавливаете PHp-CS-Fixer с помощью phive или загружаете его вручную со страницы релизов, вам необходимо обновлять PHP-CS-Fixer вручную.
Ваш проект ещё не использует composer? Почему бы не начать использовать composer, сделав PHP-CS-Fixer своей первой зависимостью при разработке?
Вы не можете использовать composer, потому что ваш проект работает на версии младше PHP 5.3? Почему бы не использовать другую версию PHP для запуска средств разработки?
Я также рекомендую использовать последнюю версию PHP-CS-Fixer, чтобы вы могли воспользоваться возможностями и исправлениями, которые разработчики постоянно добавляют в инструмент.
Вы не можете использовать последнюю версию PHP-CS-Fixer, потому что ваш проект ещё не использует PHP 7.4 или выше? Опять, почему бы не использовать другую версию PHP для запуска средств разработки?
Например, последние пару недель я был занят обновлением проекта с PHP 5.6 до PHP 8.1. После настройки локальной среды разработки, работающей на PHP 5.6 в Docker, я настроил рабочий процесс GitHub Actions, который использует PHP 8.1 для установки и запуска инструментов разработки, включая PHP-CS-Fixer.
Если я могу использовать PHP 8.1 для запуска инструментов разработки проекта, работающего на PHp 5.6, то и вы сможете.
Ключом к успеху является тщательная настройка инструментов разработки.
Добавление базовой конфигурации для PHP-CS-Fixer
PHP-CS-Fixer требует две вещи для отчёта и исправления нарушений стандарта кодирования: список проверяемых файлов, и конфигурацию правил и наборов правил, которые он использует для создания и настройки соответствующих средств исправления.
Файл конфигурации .php-cs-fixer.php приведённый ниже, настраивает finder в setFinder($finder) и пустой массив правил в setRules([]).
<?php
$finder = PhpCsFixer\Finder::create()
->exclude([
'.build/',
'.docker/',
'.github/',
])
->ignoreDotFiles(false)
->in(__DIR__)
->name('.php-cs-fixer.php');
$config = new PhpCsFixer\Config();
$config
->setFinder($finder);
->setRules([]);
return $config;
finder позволяет настроить список каталогов, исключений, имён файлов и т.д. и возвращает список файлов, которые должен проверять PHP-CS-Fixer.
В зависимости от макета вашего проекта, ваша конфигурация finder может выглядеть по-другому.
Пустой массив правил переопределит конфигурацию правил по умолчанию. PHP-CS-Fixer анализирует файл PHP до и после применения средств исправления, чтобы гарантировать, что он не пытается исправить файл, содержащий недопустимый PHP код, и не оставит после себя файл с недопустимым PHP-кодом. Когда PHP-CS-Fixer находи файл, который содержит недопустимый PHP-код, он пропустит его исправление и выдаст предупреждение.
Даже с пустым набором правил PHP-CS-Fixer является ценным инструментом, поскольку он может найти файлы содержащие недопустимый PHP-код.
Теперь, когда у вас есть первоначальная конфигурация для PHp-CS-Fixer, пришло время приступить к работе с PHP-CS-Fixer.
Запуск PHP-CS-Fixer в GitHub Actions
Как уже упоминалось, вам необходимо запускать PHP-CS-Fixer в двух средах: в среде непрерывной интеграции и в локальной среде разработки.
Следующая команда запускает PHp-CS-Fixer с параметром --dry-run и сообщает о нарушениях стандарта кодирования:
vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --diff --dry-run --verboseВ зависимости от того, как вы установили PHP-CS-Fixer и назвали файл конфигурации, команда может выглядеть по-разному.
Но важно использовать параметр --dry-run при запуске PHP-CS-Fixer в системе непрерывной интеграции: PHP-CS-Fixer завершит своё выполнение с ненулевым кодом выхода, когда обнаружит нарушения стандарта кодирования и прервёт сборку.
Я чувствую себя в GitHub как дома и люблю использовать GitHub Actions как систему непрерывной интеграции. Приведённый ниже рабочий процесс GitHub Actions выполнит Checkout вашего репозитория, настроит PHP, установит зависимости с помощью composer и запустит PHP-CS-Fixer с параметром --dry-run.
name: "Integrate"
on:
pull_request: null
push:
branches:
- "main"
jobs:
coding-standards:
name: "Coding Standards"
runs-on: "ubuntu-latest"
strategy:
matrix:
php-version:
- "8.1"
steps:
- name: "Checkout"
uses: "actions/checkout@v3.5.0"
- name: "Set up PHP"
uses: "shivammathur/setup-php@v2.24.0"
with:
coverage: "none"
php-version: "$NaN"
- name: "Validate composer.json and composer.lock"
run: "composer validate --ansi --no-check-publish"
- name: "Install locked dependencies with composer"
run: "composer install --ansi --no-interaction --no-progress"
- name: "Run friendsofphp/php-cs-fixer"
run: "vendor/bin/php-cs-fixer fix --ansi --config=.php-cs-fixer.php --diff --dry-run --verbose"В зависимости от настройки вашего проекта и системы непрерывной интеграции ваша конфигурация может отличаться, но шаги будут примерно такими же.
С помощью этого рабочего процесса GitHub Actions вы не сможете закоммитить и запушить PHP-код, который не соответствует вашим стандартам кодирования, без сбоя сборки.
Вы можете улучшить работу по стандартам кодирования, кэшируя зависимости, установленные с помощью composer в файл кэша PHP-CS-Fixer между запусками.
Запуск PHP-CS-Fixer в среде разработки
Следующая команда запустит PHP-CS-Fixer и исправит нарушения стандарта кодирования:
vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --diff --verboseВ зависимости от того, ка вы установили PHP-CS-Fixer и назвали файл конфигурации, команды может отличаться. Опять, вам не нужны сообщения о нарушениях стандарта кодирования в среде разработки; вам нужны исправления.
Эта команда немного длинная для ввода, и если вы хотите часто запускать PHp-CS-Fixer, вы, вероятно захотите использовать запуск задач или какой-либо другой инструмент облегчающий запуск инструментов в среде разработки.
Если вы используете Makefile, добавьте в свой Makefile цель coding-standards.
.PHONY: coding-standards
coding-standards: vendor
vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --diff --verbose
vendor: composer.json composer.lock
composer validate --strict
composer install --no-interaction --no-progressУстановив цель coding-standards в свой Makefile, вы можете выполнить следующую команду, чтобы позволить PHp-CS-Fixer исправить нарушения стандартов кодирования:
make coding-standardsЕсли вы предпочитаете сценарии composer, добавьте сценарий coding-standards в ваш composer.json.
{
"scripts": {
"coding-standards": "@php vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --diff --verbose"
}
}Задав сценарий coding-standards в файле composer.json, вы можете запустить следующую команду, чтобы позволить PHP-CS-Fixer исправить нарушения стандартов кодирования:
composer coding-standardsРазвитие конфигурации PHP-CS-Fixer
теперь, когда вы используете PHP-CS-Fixer в своей системе непрерывной интеграции и среде разработки, осталось одно: вы хотите, чтобы PHP-CS-Fixer применял исправления совместимые с версией PHP, которую вы используете в продакшене, а пока у вас только пастой массив правил.
Вот что хорошо помогло мне.
Во-первых, получите полный список правил для всех доступных исправлений, например из Пользовательского набора правил в ergebnis/php-cs-fixer-config-template.
Во-вторых, настройте конфигурацию правил, отключив все исправления. На момент написания статьи было около 250 правил.
<?php
$finder = PhpCsFixer\Finder::create()
->exclude([
'.build/',
'.docker/',
'.github/',
])
->ignoreDotFiles(false)
->in(__DIR__)
->name('.php-cs-fixer.php');
$config = new PhpCsFixer\Config();
$config
->setFinder($finder);
->setRules([
'align_multiline_comment' => false,
'array_indentation' => false,
'array_push' => false,
'array_syntax' => false,
// ...
'visibility_required' => false,
'void_return' => false,
'whitespace_after_comma_in_array' => false,
'yoda_style' => false,
]);
return $config;
В качестве альтернативы, если вы уже делитесь конфигурациями PHP-CS-Fixer между проектами, переопределите существующую конфигурацию правил, отключив все правила.
В-третьих, просмотрите список правил сверху вниз, снизу вверх или как вам больше подходит, а затем включите и настройте по одному правилу за раз — но только тогда, когда это возможно. Убедитесь, что применяются исправления совместимые с вашей версией PHP, работающей в продакшене.
Пример одновременного включения и настройки правила
Давайте рассмотрим конкретные примеры, рассматривая и настраивая правило array_syntax, когда вы работаете с pull request и обзорами кода перед слияниями.
- Сначала создайте ветку, например
feature/array-syntax. - Скопируйте имя правила.
- Перейдите на https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.16.0 (измените 3.16.0 версией PHP-CS-Fixer, которую используете). Нажмите T, чтобы открыть навигацию по файлам. Вставьте имя правила в поле ввода (в данном случае
array-syntax). Выберите файл документации в раскрывающемся списке (array_syntax.rst). - Проверьте документацию. Можно ли безопасно включить средство исправления
array-syntax? Например, в PHP 5.4 появился сокращённый синтаксис массива. Ваш легаси PHP-проект работает на PHP 5.3 в продакшене? Тогда вам, вероятно следует включить средство исправленияarray_syntaxи указать параметруsyntaxзначениеlong(['syntax' => 'long']). Или ваш легаси проект работает на PHP 5.4 или выше? Тогда вам, вероятно следует включить средство исправления и указать параметруsyntaxзначениеshort(['syntax' => 'short']). - Сделайте коммит и пуш изменений файла конфигурации
.php-cs-fixer.php. - Откройте pull request и задокументируйте в теле, что этот pull request активирует
array_syntaxсредство исправления. Открытие pull request запустит рабочий процесс GitHub Actions. - Запустите PHP-CS-Fixer в вашей среде разработки. Если PHp-CS-Fixer применил исправления, рабочий процесс GitHub Actions завершится ошибкой. Сделайте коммит и пуш исправлений отдельным коммитом, чтобы сборка прошла успешно.
- Посмотрите изменения в pull request и убедитесь, что они имеют смысл. При необходимости попросите кого-нибудь ещё посмотреть ваш pull request.
- Выполните слияние pull request и удалите ветку.
- Проверьте ветку по умолчанию в среде разработки.
- Получите из репозитория последние изменения.
- Удалите ветку
feature.
Повторите описанные шаги для каждого правила.
Вы можете найти пример pull request, который включает и настраивает средство исправления синтаксиса array_syntax для официального веб-сайта PHP здесь
Недостатки включения и настройки одного правила за раз
На момент написания этой статьи PHP-CS-Fixer поставляется с 250 правилами. Включение и конфигурирование одного правила за раз может занять некоторое время, особенно если вы работаете с pull request и требуете ревью кода перед слиянием. Но вы можете значительно ускорить процесс используя Ship/Show/Ask
Если вы не хотите тратить время, удачи вам в применении всех правил и одновременном просмотре всех исправлений!
Преимущества включения и настройки одного правила за раз
На мой взгляд, включение и настройка одного правила за раз имеет следующие преимущества:
- Вы минимизируете риск: каждый pull request содержит только связанные изменения, которые легче просмотреть.
- Вы приглашаете других разработчиков к совместной работе над вашим стандартом кодирования.
- Вы, вероятно, коснётесь кода во всех уголках вашего легаси PHP-проекта, что позволит обнаружить и отметить странные места, требующие более тщательного изучения.