Установка и использование php-cs-fixer

Источник: «Installing and using php-cs-fixer»
В этой статье мы рассмотрим различные способы установки и использования php-cs-fixer. Мы увидим, что всё не так очевидно, как кажется. Поехали! 😎

Оглавление

Предварительное условие

Я предполагаю, что вы обладаете хотя бы базовыми знаниями о PHP, Symfony и Composer.

Конфигурация

Введение

Php-cs-fixer — это отличный инструмент, позволяющий автоматически исправлять стиль кодирования вашего PHP-кода. Он пользуется популярностью в PHP-сообществе и стал одним из любимых инструментов многих PHP-разработчиков. Однако его установка в проект может вызвать вопросы и привести к проблемам, о которых мы расскажем в следующих главах.

Цель

Мы рассмотрим все способы установки и использования php-cs-fixer для проекта, а также их плюсы и минусы.

Проблема

Что? Статья в блоге об установке php-cs-fixer? Вы что, издеваетесь? Разве это не так же просто, как запустить:

composer require --dev friendsofphp/php-cs-fixer

Давайте проверим.

Бета-версия Symfony 7.0 вышла уже несколько дней назад (в этот момент я начал писать эту статью в блоге). Давайте попробуем; мы можем создать новый проект Symfony 7 с помощью бинарника Symfony:

symfony new my_project_directory --version=7.0.x-dev

Теперь давайте установим php-cs-fixer:

cd my_project_directory
composer require --dev friendsofphp/php-cs-fixer
./composer.json has been updated
Running composer update friendsofphp/php-cs-fixer
Loading composer repositories with package information
Restricting packages listed in "symfony/symfony" to "7.0.*"
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

Problem 1
- friendsofphp/php-cs-fixer v0.1.0 requires symfony/console 2.1.* -> found symfony/console[v2.1.0, ..., 2.1.x-dev] but it conflicts with your root composer.json require (7.0.*).
- ...
- friendsofphp/php-cs-fixer v3.4.0 requires symfony/console ^4.4.20 || ^5.1.3 || ^6.0 -> found symfony/console[v4.4.20, ..., 4.4.x-dev, v5.1.3, ..., 5.4.x-dev, v6.0.0-BETA1, ..., 6.4.x-dev] but it conflicts with your root composer.json require (7.0.*).
- friendsofphp/php-cs-fixer[dev-release_notes_template, dev-master, v3.5.0, ..., v3.37.1] require symfony/console ^5.4 || ^6.0 -> found symfony/console[v5.4.0-BETA1, ..., 5.4.x-dev, v6.0.0-BETA1, ..., 6.4.x-dev] but it conflicts with your root composer.json require (7.0.*).
- Root composer.json requires friendsofphp/php-cs-fixer * -> satisfiable by friendsofphp/php-cs-fixer[dev-release_notes_template, dev-master, v0.1.0, ..., v0.5.7, v1.0, ..., v1.13.3, v2.0.0-alpha, ..., v2.19.3, v3.0.0-beta.1, ..., v3.37.1, 9999999-dev].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require friendsofphp/php-cs-fixer:*" to figure out if any version is installable, or "composer require friendsofphp/php-cs-fixer:^2.1" if you know which you need.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.

Бум 💥! Не работает; Composer не может разрешить зависимости, так как php-cs-fixer использует "symfony/console": "^5.4 || ^6.0", который не может быть разрешён при использовании Symfony 7.0 beta.

Я знаю, что вы думаете: 🤔.

Это версия Symfony BETA; вот почему она не работает.

Это кажется правильным объяснением, но оно неверно: проблема исходит от вендора php-cs-fixer, а не от Symfony. И у нас нет абсолютно никаких гарантий, когда она будет исправлена. Она может быть исправлена быстро, но вы также можете ждать долгое время, и, возможно, что ещё хуже, вам придётся делать форк самой библиотеки.

PS: Теперь это исправлено! chore: Add support for Symfony 7 #7453🎉

Напоминаем, что php-cs-fixer — это PHP-библиотека и имеет свои зависимости. Давайте посмотрим на её собственный файл composer.json:

"require": {
"php": "^7.4 || ^8.0",
"ext-json": "*",
"ext-tokenizer": "*",
"composer/semver": "^3.3",
"composer/xdebug-handler": "^3.0.3",
"sebastian/diff": "^4.0 || ^5.0",
"symfony/console": "^5.4 || ^6.0",
"symfony/event-dispatcher": "^5.4 || ^6.0",
"symfony/filesystem": "^5.4 || ^6.0",
"symfony/finder": "^5.4 || ^6.0",
"symfony/options-resolver": "^5.4 || ^6.0",
"symfony/polyfill-mbstring": "^1.27",
"symfony/polyfill-php80": "^1.27",
"symfony/polyfill-php81": "^1.27",
"symfony/process": "^5.4 || ^6.0",
"symfony/stopwatch": "^5.4 || ^6.0"
},
"require-dev": {
"facile-it/paraunit": "^1.3 || ^2.0",
"justinrainbow/json-schema": "^5.2",
"keradus/cli-executor": "^2.0",
"mikey179/vfsstream": "^1.6.11",
"php-coveralls/php-coveralls": "^2.5.3",
"php-cs-fixer/accessible-object": "^1.1",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1",
"phpspec/prophecy": "^1.16",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"symfony/phpunit-bridge": "^6.2.3",
"symfony/yaml": "^5.4 || ^6.0"
},

Мы видим компонент Symfony (symfony/console), препятствующий установке в проект. Мы также понимаем, что php-cs-fixer поставляется со многими другими вендорами, особенно в секции -dev, поскольку это инструмент.

Так что да, есть вероятность возникновения конфликтов в вашем проекте. Чем больше у вас зависимостей, тем больше вероятность возникновения проблем с зависимостями при установке нового вендора. Но, конечно, это не относится только к php-cs-fixer; у нас также есть эта проблема со всеми другими библиотеками PHP.

Итак, этот метод не работает для нового блестящего проекта Symfony 7 BETA; давайте посмотрим остальные методы и то, как мы можем это исправить. Но сначала, что насчёт Symfony сообщества?

Что делают другие разработчики

Мне стало любопытно, и я хотел узнать, чем пользуются другие разработчики Symfony. Я создал небольшой опрос в Symfony Slack. Несмотря на то, что ответов не так много (30), мы можем увидеть тенденции. Вот что я опубликовал:

Привет всем, быстрый опрос: как вы устанавливаете замечательную библиотеку php-cs-fixer?

  1. В секции require-dev файла composer моего проекта -> composer require --dev friendsofphp/php-cs-fixer
  2. В выделенном файле composer.json -> composer require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer
  3. При глобальной установке composer -> composer global require friendsofphp/php-cs-fixer
  4. С помощью docker -> docker run --rm -v $(PWD):/data cytopia/php-cs-fixer fix --dry-run --diff --allow-risky=yes ($PWD в fishshell)

Результаты оказались следующими:

Опрос о методе установки php-cs-fixer
Опрос о методе установки php-cs-fixer

Итак, установка php-cs-fixer в раздел require-dev проекта по-прежнему остаётся любимым методом большинства разработчиков Symfony. Давайте попробуем другие.

Метод 2: Использование выделенного composer.json-файла внутри проекта

Должен признаться, что я не использовал этот метод (до сих пор). В чем разница с методом require-dev? На этот раз мы устанавливаем зависимости не в проект, а в подкаталог. Если посмотреть документацию по php-cs-fixer, то это даже считается лучшей практикой. Давайте попробуем:

mkdir -p tools/php-cs-fixer
composer require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer
/composer.json has been created
Running composer update friendsofphp/php-cs-fixer
Loading composer repositories with package information
Updating dependencies
Lock file operations: 25 installs, 0 updates, 0 removals
- Locking composer/pcre (3.1.1)
...
- Installing friendsofphp/php-cs-fixer (v3.38.0): Extracting archive
Generating autoload files
22 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
Using version ^3.38 for friendsofphp/php-cs-fixer

Поскольку инструмент устанавливается в собственную директорию, то, конечно, никаких конфликтов быть не может. И мы можем его использовать:

tools/php-cs-fixer/vendor/bin/php-cs-fixer fix src
Loaded config default.
Fixed 0 of 1 files in 0.007 seconds, 14.000 MB memory used

Файл конфигурации MicroSymfony — хорошее начало при создании нового набора правил для вашего проекта. Он лаконичен, я включил в него только самое необходимое. Не стесняйтесь использовать его и адаптировать к своему проекту. Хорошо, теперь у нас есть рабочая конфигурация для нашего проекта Symfony. Давайте посмотрим на оставшиеся методы.

Метод 3: С глобальной установкой composer

composer global require friendsofphp/php-cs-fixer

Этот метод также позволяет избежать конфликтов с вашим проектом и даже не включается в него. Вместо того чтобы использовать относительный путь, вы можете указать свой путь к php-cs-fixer, а затем вызвать:

php-cs-fixer fix src

Я не очень люблю этот метод, потому что php-cs-fixer отсоединяется от вашего проекта, но он работает.

Метод 4: С Docker

Как мы видели в нашем опросе, это не самый популярный метод, но очень прагматичный подход. Цель состоит в том, чтобы использовать существующий образ Docker, содержащий всё необходимое для запуска php-cs-fixer. Мы можем использовать, например, репозиторий cytopia/docker-php-cs-fixer. Мы можем запустить задачу по исправлению с помощью следующей команды Docker:

docker run --rm -v ./:/data cytopia/php-cs-fixer fix --allow-risky=yes

Он использует последний доступный образ (в настоящее время это версия 3 для PHP 8.1). Поскольку этот проект содержит несколько образов, мы также можем использовать его для запуска php-cs-fixer на легаси кодовой базе , использующей PHP 7.4 (Внедрение PHP-CS-Fixer в легаси PHP-проекты); в этом случае мы можем выполнить:

docker run --rm -v ./:/data cytopia/php-cs-fixer:3-php7.4 fix --allow-risky=yes

Плюс в том, что нам не нужно ничего устанавливать; нам нужен только Docker. Минус в том, что мы не контролируем содержимое образа; как мы видим, последняя доступная версия не является последней версией php-cs-fixer (на данный момент 3.42).

docker run --rm -v ./:/data cytopia/php-cs-fixer:latest-php8.1 --version
PHP CS Fixer 3.17.0 (3f0ed86) Brazilian Kangaroo by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 8.1.20

Итог

Мы можем свести все плюсы и минусы в следующую таблицу (Я сократил названия столбцов, не стал писать полностью название каждого метода, как в оригинале. Добавил ссылки на каждый метод.).

Метод 1Метод 2Метод 3Метод 4
Не засоряете проект зависимостями
Быстрый анализ(1)
Точный контроль версии php-cs-fixer
По-прежнему связан с проектом
Не требуется локальная установка

(1) Использование Docker немного влияет на производительность при запуске, но разница во времени анализа кажется незначительной. Я проведу другие, более точные тесты, чтобы подтвердить это. Проблема заключается в разнице версий (с опозданием на 24 минорные версии), поэтому сравнение не совсем корректно.

Заключение

Мы рассмотрели разные способы установки php-cs-fixer. Я изменил своё мнение; раньше было очевидно, что установка этого инструмента в основной composer проекта — это хорошая практика и правильный путь. Теперь я думаю, что установка инструмента в отдельную директорию с собственным файлом composer.json более безопасна и элегантна. Когда мы хотим запустить php-cs-fixer, всё, что нам нужно, это использовать ./tool/php-cs-fixer/vendor/bin/php-cs-fixer вместо ./vendor/bin/php-cs-fixer. Мы сохраняем зависимости проекта настолько минимальными, насколько это возможно. Тем не менее инструмент установленный в репозитории проекта, легко обновляется и работает быстро; мы имеем лучшее из двух миров.

Вот и всё! Надеюсь, вам понравилось. Проверьте ссылки ниже, чтобы получить дополнительную информацию, связанную с этим постом. Как всегда, приветствуются отзывы, лайки и ретвиты. (см. поле ниже) До встречи! COil. 😊

Дополнительные материалы

Предыдущая Статья

Игнорирование файлов в Git. Больше, чем просто .gitignore

Следующая Статья

Руководство для начинающих по блочной модели CSS