
Переход с PHP 7.4 на PHP 8: пошаговый план миграции
Переход с PHP 7.4 на PHP 8 безопасен, если заранее проверить совместимость: обновить зависимости, прогнать статанализ и тесты, затем выкатывать поэтапно.
Переход с PHP 7.4 на PHP 8: что нужно знать до начала
Перейти с PHP 7.4 на PHP 8 можно без остановки проекта, если действовать по порядку: проверить совместимость кода и библиотек, поймать ошибки статическим анализом и тестами, проверить работу на staging и выкатывать поэтапно с возможностью отката.
В этой статье разберём, зачем обновляться, какие изменения в PHP 8 действительно ломают старый код, какими инструментами автоматизировать проверку и как построить безопасный план миграции. Материал подойдёт и для небольшого сайта на CMS, и для крупного приложения на Laravel, Symfony или самописном ядре.
Почему откладывать обновление опасно
Главный довод за миграцию не новые возможности, а безопасность. Когда ветка PHP выходит из поддержки, найденные уязвимости в ней больше не закрываются. Если вы работаете на 7.4, любая новая брешь в интерпретаторе остаётся с вами навсегда. Хостинг-провайдеры постепенно убирают такие версии из панели управления, а сканеры безопасности и требования заказчиков помечают устаревший PHP как риск.
Вторая причина экосистема. Современные версии популярных пакетов, фреймворков и CMS постепенно поднимают минимальную версию PHP. Пока вы сидите на 7.4, вы не получаете обновления зависимостей, и технический долг растёт. Чем дольше пауза, тем больше накопленных изменений придётся разбирать за один раз.
Третья причина инженерная. Код на PHP 8 проще читать и поддерживать: появились именованные аргументы, атрибуты, promotion свойств в конструкторе, union-типы, выражение `match` и nullsafe-оператор. Всё это сокращает шаблонный код и делает типы явными.
Что вы получаете после перехода на PHP 8
- 01
Актуальные исправления безопасности и поддержку, пока выбранная ветка находится в жизненном цикле
- 02
Доступ к свежим версиям фреймворков, CMS и Composer-пакетов, которые уже не поддерживают 7.4
- 03
Более строгую и предсказуемую работу с типами: ошибки, которые раньше молча скрывались, становятся заметными
- 04
Современный синтаксис: `match`, nullsafe `?->`, именованные аргументы, атрибуты, constructor promotion, union-типы
- 05
Новые функции `str_contains()`, `str_starts_with()`, `str_ends_with()`, которые заменяют громоздкие проверки через `strpos()`
- 06
JIT-компилятор и общие оптимизации движка: заметный прирост на вычислениях и умеренный в типичных веб-задачах
Где сейчас находится 7.4 и куда двигаться
Даты указаны по официальному графику PHP на момент подготовки статьи. Перед планированием релиза сверьтесь со страницей поддерживаемых версий на сайте php.net.
Какую версию PHP 8 выбирать
Формально вы переходите «на PHP 8», но на практике нужно выбрать конкретную ветку: 8.0, 8.1, 8.2, 8.3 или новее. Останавливаться на 8.0 бессмысленно: она уже вышла из поддержки, и вы окажетесь в той же ситуации, что и сейчас. Выбирайте ветку, у которой впереди есть хотя бы год-два жизненного цикла, и убедитесь, что её поддерживают ваши хостинг, CMS и ключевые пакеты.
Переход через несколько версий сразу допустим, но тогда в тестах нужно учитывать депрекейты каждой промежуточной ветки. Например, в 8.1 устарела передача `null` в необязательные для null параметры внутренних функций, в 8.2 объявлены устаревшими динамические свойства классов, а в 8.4 неявные nullable-типы параметров. Эти предупреждения не ломают работу, но засоряют логи и в будущих версиях превратятся в ошибки.
Что действительно ломается при переходе с 7.4 на 8.0
Большинство проектов упирается в несколько повторяющихся групп проблем. Разберём их по степени распространённости.
1. Сравнение строк и чисел. В PHP 8 изменена логика нестрогого сравнения. Раньше `0 == 'abc'` возвращало `true`, потому что строка приводилась к числу. Теперь число приводится к строке, если вторая сторона не является числовой, и результат будет `false`. Такой код часто встречается в проверках прав доступа, статусов и условий в шаблонах.
2. Ошибки вместо тихих предупреждений. Внутренние функции теперь выбрасывают `TypeError` и `ValueError` при неверных аргументах, а не возвращают `null` или `false` с предупреждением. Арифметика и побитовые операции над массивами, ресурсами и объектами тоже приводят к `TypeError`.
3. Необъявленные переменные и ключи. Обращение к несуществующей переменной или ключу массива теперь даёт Warning, а не Notice. Если на проде включён вывод ошибок или обработчик превращает предупреждения в исключения, сайт может начать падать там, где раньше работал.
4. Удалённые возможности. Исчезли `create_function()`, `each()`, приведение `(real)`, доступ к символам строки через фигурные скобки `$str{0}`, а также методы-конструкторы в стиле PHP 4 (метод с именем класса).
5. Объекты вместо ресурсов. Функции расширений curl, GD, XML и других теперь возвращают объекты (`CurlHandle`, `GdImage` и т. д.). Проверка `is_resource()` на таких значениях вернёт `false`.
6. Приоритет оператора конкатенации. Знаки `+` и `-` теперь имеют более высокий приоритет, чем точка. Выражение вида `'Итого: ' . $a + $b` теперь вычисляется иначе, чем в 7.4. Лучше явно расставить скобки.
Три изменения, которые чаще всего ломают рабочий код
42 == '42abc'0 == 'abc'is_resource(curl_init())Во всех трёх случаях код не падает с ошибкой, а молча меняет поведение. Именно поэтому такие места опаснее явных исключений и их нужно искать заранее.
| Как было в PHP 7.4 | Как в PHP 8 | Что делать |
|---|---|---|
| Ошибка во внутренней функции давала предупреждение и возврат null или false | Выбрасывается TypeError или ValueError | Проверять входные данные и обернуть рискованные вызовы в try/catch там, где это оправдано |
| Необъявленная переменная или ключ массива давали Notice | Выдаётся Warning: Undefined variable, Undefined array key | Инициализировать переменные, использовать isset(), ?? и array_key_exists() |
| create_function() и each() работали (с депрекейтом) | Функции удалены, вызов приводит к фатальной ошибке | Заменить на анонимные функции и foreach |
| Символ строки можно было получить через $str{0} | Синтаксис удалён, остаются квадратные скобки $str[0] | Перейти на квадратные скобки или mb_substr() для многобайтных строк |
| curl_init() и imagecreate() возвращали resource | Возвращаются объекты CurlHandle и GdImage | Заменить is_resource() на проверку instanceof или сравнение с false |
Чем автоматизировать проверку совместимости
Искать такие места глазами в проекте на сотни файлов неэффективно. Для этого есть инструменты, и использовать их лучше в связке.
Статический анализ. PHPStan и Psalm находят вызовы с неверными типами аргументов, обращения к несуществующим свойствам и методам, потенциально неинициализированные переменные. Запустите их на целевой версии PHP и начните с умеренного уровня строгости, поднимая его постепенно.
Проверка совместимости. Набор правил PHPCompatibility для PHP_CodeSniffer сканирует код на использование удалённых и устаревших возможностей для выбранной версии. Он быстро даёт список мест, которые точно нужно править.
Автоматический рефакторинг. Rector умеет безопасно переписывать типовые конструкции под новую версию: заменять `strpos()` на `str_contains()`, добавлять promotion свойств, обновлять устаревший синтаксис. Всегда просматривайте дифф перед коммитом, а не принимайте изменения вслепую.
Зависимости. Команда `composer why-not php 8.3` покажет, какие пакеты блокируют обновление. Часть библиотек потребуется обновить, а заброшенные заменить на живые аналоги или форкнуть.
Тесты. Никакой анализатор не заменит прогон автотестов на новой версии. Если покрытия нет, хотя бы напишите smoke-тесты на ключевые сценарии: авторизацию, оформление заказа, формы, API.
Пошаговый план миграции на PHP 8
- 01
Проведите инвентаризацию. Выпишите текущую версию PHP, список расширений (`php -m`), версии CMS или фреймворка, все Composer-пакеты и плагины, а также cron-скрипты и воркеры очередей.
- 02
Зафиксируйте целевую версию и проверьте, поддерживают ли её хостинг, веб-сервер, база данных и ваша CMS. Если нужно, сначала обновите фреймворк или CMS до версии, совместимой с PHP 8.
- 03
Обновите зависимости. Измените ограничение `php` в `composer.json`, выполните `composer update` в отдельной ветке и разберите конфликты. Заброшенные пакеты заменяйте или форкайте.
- 04
Запустите PHPCompatibility, PHPStan или Psalm и исправьте найденное. Типовые правки автоматизируйте через Rector, а результат проверяйте вручную.
- 05
Поднимите staging-окружение с той же версией PHP и теми же расширениями, что планируются на проде. Включите `error_reporting = E_ALL` и логирование, прогоните автотесты и ручные сценарии.
- 06
Проверьте производительность и память: сравните время ответа, нагрузку на CPU и потребление памяти на типичных страницах и тяжёлых запросах до и после обновления.
- 07
Выкатите поэтапно. Если инфраструктура позволяет, переведите на PHP 8 сначала часть трафика или один сервер, наблюдайте за логами и метриками, затем остальные. Заранее подготовьте быстрый откат на 7.4.
Конфигурация и расширения не забываем
Код это только половина миграции. После смены версии стоит перепроверить `php.ini` и конфигурацию пула PHP-FPM: значения по умолчанию и поведение некоторых директив менялись. Убедитесь, что установлены все нужные расширения именно под PHP 8: `mbstring`, `intl`, `curl`, `gd` или `imagick`, `pdo_mysql` или `pdo_pgsql`, `opcache`, `redis`, `zip`. Расширения из PECL нужно ставить заново под новую версию, а старые бинарные сборки не подойдут.
Отдельно проверьте OPcache и JIT. OPcache нужно включать в любом случае, он даёт основной выигрыш в скорости. JIT включайте осознанно и только после замеров: для типичного сайта на CMS он почти не меняет результат, а вот в вычислительных задачах может помочь заметнее.
Не забудьте про окружение разработки. Docker-образы, CI-пайплайны, локальные среды и конфигурации IDE должны использовать ту же версию PHP, что и прод. Иначе ошибки будут выявляться уже после релиза.
Типичные ошибки при обновлении PHP
Как делают неправильно
- Обновляют PHP сразу на продакшене без staging-окружения
- Скрывают предупреждения через `error_reporting(0)` или оператор `@`, чтобы «всё заработало»
- Не проверяют Composer-зависимости и плагины CMS, а потом получают белый экран
- Опираются только на то, что главная страница открылась
- Не готовят план отката и не делают резервную копию
Как правильно
- 01
Тестировать на staging с идентичным окружением и копией реальных данных
- 02
Включить `E_ALL`, собрать предупреждения в логи и исправить их причины, а не симптомы
- 03
Заранее выполнить `composer why-not` и проверить совместимость каждого плагина и темы
- 04
Прогнать сценарии: авторизация, формы, оплата, личный кабинет, API, cron, очереди
- 05
Сделать бэкап, сохранить рабочий пул 7.4 и выкатывать поэтапно
Что отслеживать после релиза
Выкатив PHP 8, не расслабляйтесь сразу. Первые часы и дни следите за логами ошибок PHP и веб-сервера, ростом числа 5xx-ответов, временем ответа и потреблением памяти. Часть проблем проявляется только на редких сценариях: ночных cron-задачах, экспорте отчётов, обработке старых записей.
Для сайтов, которые зависят от поискового трафика, добавьте внешний контроль. Яндекс Вебмастер и Google Search Console покажут ошибки обхода, недоступность страниц и проблемы с индексацией. Яндекс Метрика и Google Analytics помогут увидеть всплески отказов, падение конверсии или проседание скорости загрузки. Если после релиза появились скачки 5xx или аномалии в поведении, откатывайтесь и разбирайтесь на staging, а не чините на живом трафике.
Готов ли проект к PHP 8
- composer updateпроходит без конфликтов на целевой версии
- PHPCompatibility и PHPStan не показывают критичных ошибок
- Автотесты и ручные сценарии пройдены на staging сE_ALL
- Установлены все расширения под PHP 8, настроены OPcache и PHP-FPM
- Cron-задачи, воркеры очередей и консольные команды запущены под новой версией
- Есть свежий бэкап и отработанный сценарий отката на 7.4
Итоги: как перейти на PHP 8 спокойно
- 01
Выберите целевую ветку, у которой впереди живой жизненный цикл, и проверьте её поддержку хостингом и платформой
- 02
Обновите зависимости и прогоните PHPCompatibility, PHPStan или Psalm и Rector
- 03
Особое внимание уделите сравнению строк с числами, ошибкам во внутренних функциях, необъявленным переменным и объектам вместо ресурсов
- 04
Протестируйте на staging с E_ALL, затем выкатывайте поэтапно с готовым планом отката
- 05
После релиза следите за логами, 5xx-ответами и данными Яндекс Вебмастера, Google Search Console, Яндекс Метрики и Google Analytics
Чем раньше вы начнёте, тем меньше изменений придётся разбирать за один раз. Если нужен второй взгляд на ваш проект, мы проведём аудит совместимости и подготовим конкретный план миграции под вашу архитектуру.
Часто задаваемые вопросы
Да, это нормальная практика. Версия 8.0 давно не поддерживается, поэтому разумно целиться сразу в актуальную ветку 8.x. Но учтите, что вы получите накопленные изменения всех промежуточных версий: 8.0, 8.1, 8.2 и далее. Прогоните код через статический анализ и тесты именно на целевой версии.
Чаще всего проблемы дают изменившееся сравнение строк с числами, новые TypeError и ValueError во внутренних функциях, повышение серьёзности ошибок для необъявленных переменных и ключей массива, удалённые функции (create_function, each), смена resource на объекты в curl и GD, а также несовместимые версии библиотек в Composer.
Обычно да, но скромно. Для типичного веб-приложения на CMS или фреймворке прирост составляет единицы или десятки процентов. JIT-компилятор заметнее помогает в вычислительных задачах. Основной выигрыш от миграции в безопасности, поддержке библиотек и современном синтаксисе. Измеряйте результат на своём проекте.
Следите за 5xx-ошибками и скоростью ответа в логах сервера. Отслеживайте индексацию и ошибки обхода в Яндекс Вебмастере и Google Search Console, а поведение пользователей и время загрузки в Яндекс Метрике и Google Analytics. Если сайт отвечает стабильно и без ошибок, позиции не пострадают.
Обновим PHP на вашем проекте без простоя и потери данных
Проведём аудит совместимости кода и зависимостей и составим пошаговый план миграции на PHP 8
Спасибо за заявку!
Мы свяжемся с вами в ближайшее время.
Миграции проводим на staging с откатом



