Внедрение 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-проекта, что позволит обнаружить и отметить странные места, требующие более тщательного изучения.