Безопасное обновление с PHP 7.4 до 8.1 с Rector

Источник: «Safely upgrade from PHP 7.4 to 8.1 using Rector»
Если кратко изложить суть статьи, то она сводится к одному: Вам просто нужно попробовать Rector. Пусть тесты ломаются, просто запустите его.

Я должен сказать это в самом начале, единственное, что приближает к безопасному обновлению кодовой базы, — это наличие надёжного набора безопасных автоматических тестов. Ничто не даёт большего комфорта, чем куча зелёных галочек, танцующих на экране.

С учётом сказанного, мы собираемся обновить проект Laravel, работающий на PHP 7.4, который скоро перестанет поддерживаться (28 ноября). На данный момент (25 Сентября 2022) последней стабильной версией PHP является 8.1, и мы собираемся перейти на неё с помощью инструмента под названием Rector. Rector поможет нам очень удобно перейти к новому синтаксису.

Без лишних слов, вот шаги, которые я выполнил.

Изменить composer.json на новый PHP 8.1

"require": {
"php": "^8.1",
...
}

Наряду с ручным изменением версии в composer.json я также изменил среду для использования PHp 8.1. В Homestead это делается простым запуском php81. В Valet командой valet use php@8.1. Если вы работаете в Windows и используете Wamp или Xampp, что ж, удачи 😁 (на самом деле, это не так уж и сложно).

Выполнить composer update

После изменения окружения я запустил красивое и рискованное composer update. Не совсем уверен в этом, так как может быть есть чистый способ, но я думаю, что composer необходимо проверить и обновить все пакеты до указанной версии PHP.

Это тот момент, когда вы, вероятно, застрянете и столкнётесь с ошибками composer, потому что е все используемые вами пакеты поддерживают новый PHP.

Проверьте пакеты, которые могут сломаться

В этом конкретном приложении единственным пакетом, у которого не было поддержки, был fzaninotto/faker, и это потому, что проект пожелал всем спокойной ночи с 2020 года. Хорошие новости в том, что есть альтернатива fakerphp/faker, которую можно заменить непосредственно в composer.json ("fzaninotto/faker" => "fakerphp/faker"). И не нужно ничего менять в фабриках, это просто работает.

Запустите тесты

В этот момент я запускаю тесты и замечаю, что ничего не сломалось, все проходят. Однако, если у вас всё идёт не так гладко или нет тестов, ознакомьтесь с устаревшими методами и функциями PHP здесь. Убедитесь, что вы сними справились. Игнорируйте новый синтаксис, потому что мы не собираемся переходить на него по старинке. Создайте коммит со своими изменениями, чтобы у вас был чистый лист для изменений синтаксиса.

Установите, настройте и запустите Rector

composer require rector/rector --dev
vendor/bin/rector init

Эта команда установит Rector и создаст файл rector.php в корне вашего проекта. Вы можете изменить его, чтобы указать Rector обновить всю кодовую базу до PHP 8.1 с помощью этой конфигурации:

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__ . '/app',
]);

$rectorConfig->importNames();

$rectorConfig->sets([
LevelSetList::UP_TO_PHP_81,
]);

$rectorConfig->skip([
SpatieEnumClassToEnumRector::class,
]);
};

Мы вскоре обсудим это последнее правило, а теперь вы можете запустить vendor/bin/rector --dry-run. Если ваша кодовая база огромна, вам придётся подождать пару минут. Когда это будет сделано, вы увидите все изменения, которые должны быть применены, как git diff. Если вы пропустите --dry-run, вместо этого он выполнится и внесёт все изменения в ваш код, так что вы сможете выбрать то, что хотите сохранить в выбранном вами diff браузере.

То последнее правило SpatieEnumClassToEnumRector пропущено, потому что я использую пакет spatie/enum и не хочу, чтобы он автоматически преобразовался в нативные PHP перечисления. Причина этого в том, что в пакете Spatie есть несколько приятных хелперов, и, на мой взгляд, безопаснее перенести некоторые перечисления вручную.

Ещё одна небольшая проблема, на которую я хочу обратить внимание, связана с выражением match. Оно выполняет строгое сравнение, в отличие от switch, и это может нанести некоторый урон, если его не проверить. В качестве исправления вы можете использовать версию match (true) {...}, которая не так красива, но будет выполнять свободное сравнение, как switch.

Я не буду рассказывать, что нового в PHP 8.1 и что Rector сделает для вас, но, чёрт возьми, приятно видеть, как весь код очищается сам собой. PHPStorm поддерживает его из коробки. Вы просто должны попробовать его. Пусть тесты сломаются, просто запустите его.

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

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

Новое в Symfony 6.3 — Улучшения DX (developer experience)

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

Vim: Сохранить всё сразу