Как мы перевели сайт на 1С-Битрикс с PHP 7.4 на 8.2: разбор легаси-кода и неочевидных ошибок
Введение: почему переход на PHP 8.2 стал необходимостью для сайта на Битриксе
С февраля 2026 года 1С-Битрикс ограничивает поддержку продуктов на версиях PHP ниже 8.2. Но проблема не только в формальных сроках — PHP 7.4 перестал получать обновления безопасности ещё в ноябре 2022 года. Четыре года без исправлений уязвимостей — это риск, который не можешь игнорировать, если сайт принимает платежи и обрабатывает персональные данные клиентов.
Для servermall — крупного интернет-магазина серверного оборудования на 1С-Битрикс: Управление сайтом — вопрос стоял остро. Сайт существует с 2012 года, за это время накопился внушительный объём самописного кода: кастомные компоненты, обработчики событий, интеграция с AmoCRM, конфигураторы серверов, фильтры — всё в директории /local/. Штатные модули маркетплейса тоже добавили сложности: часть решений не обновлялась годами, у некоторых истекли лицензии, а документация давно не актуальна.
В этой статье — практический разбор перехода: что сломалось при смене версии PHP, какие паттерны ошибок повторялись, как мы их фиксили и что стоит проверить до запуска apt install php8.2.
Контекст проекта
Сайт servermall работает на редакции «1С-Битрикс: Управление сайтом — Бизнес». Каталог из нескольких тысяч товаров, конфигураторы сборки серверов, личный кабинет B2B, интеграция с AmoCRM через кастомный модуль в /local/.
Технический стек на момент начала миграции: PHP 7.4, MySQL 5.7, веб-сервер Apache с nginx-прокси. В директории /local/ около 120 PHP-файлов с бизнес-логикой, написанной в разное время разными разработчиками. Часть кода — наследие эпохи PHP 5.6, которое просто работало на 7.4 за счёт мягкой политики обратной совместимости.
При этом с определённого момента мы ввели правило: весь новый код пишем со строгими типами. Объявления declare(strict_types=1), тайп-хинты на аргументах и возвращаемых значениях, явные приведения вместо надежды на неявное — это вошло в практику задолго до PHP 8. Старый код переписывали постепенно, по мере касания. Такая дисциплина сильно сузила фронт работ при миграции: файлы, написанные по-человечески, переезжали на 8.2 без единого изменения.
Задача на миграцию — №11512 в корпоративном портале, поставлена в октябре 2024 года. Ответственный — Дмитрий Глаголев, основную работу по исправлению кода выполнил Алексей Плотников.
Что изменилось в PHP 8.x: ключевые несовместимости
Переход с 7.4 сразу на 8.2 — это прыжок через две мажорные версии (8.0 и 8.1). Главное изменение — не синтаксис, а философия: PHP перестал прощать нестрогую типизацию. Если на 7.4 можно было передать строку туда, где ожидается число, и интерпретатор молча делал приведение, то 8.2 либо выбрасывает TypeError, либо ведёт себя иначе. Вот что перестало работать из коробки:
- Обращение к нестатическим методам как к статическим — PHP 8.0 превратил notice в фатальную ошибку. Весь код вида
SomeClass::nonStaticMethod()начал падать. - Передача не-массива в
count()— PHP 8.1 выбрасывает TypeError. Если переменная может бытьnullили числом — нужна проверкаis_countable()или явное приведение к массиву. - Передача не-массива в
implode()— аналогично:implode(', ', $value)падает, если$valueне массив. Приходится оборачивать в проверки. - Конструкторы классов — PHP 8.0 убрал поддержку методов с именем класса в качестве конструктора. Старые модули маркетплейса, написанные до 2016 года, использовали этот подход.
- Short open tags
<?— директиваshort_open_tagпо умолчанию выключена в PHP 8. Если в шаблонах или скриптах встречается<?вместо<?php— белый экран. define()без кавычек —define(CONSTANT_NAME, value)вместоdefine('CONSTANT_NAME', value). В PHP 7 прокатывало, в 8 — fatal error.- Ужесточение типов в выражениях — арифметика с нечисловыми значениями, конкатенация без явного приведения, доступ к индексам не-массивов — всё это либо перестало работать, либо начало выдавать TypeError.
Что сломалось на servermall: разбор по категориям
Мы выкатили PHP 8.2 на тестовую копию сайта и методично фиксили ошибки. Всего потребовалось изменить около 50 PHP-файлов. Все исправления собирались в отдельной ветке, ответвлённой от dev — чтобы не тормозить основные разработки. Разберём по категориям.
1. Нестатические методы, вызываемые статически
Самая частая категория. В файле с обработчиками авторизации метод OnBeforeUserLoginHandler вызывался ядром Битрикса через ExecuteModuleEventEx, но не имел модификатора static. PHP 8.2 падал с ошибкой: «Non-static method cannot be called statically».
Исправление — добавить static:
// Было
function OnBeforeUserLoginHandler(&$arFields) {
// Стало
static function OnBeforeUserLoginHandler(&$arFields) {
Аналогичная ситуация в файле с основными обработчиками — метод setAdWordsTags() класса для рекламных меток вызывался статически, но был объявлен как public function. Добавили static public function.
2. count() и implode() на потенциально не-массивах
В PHP 7.4 код вроде count($curCompare) молча возвращал 0, если $curCompare был null или false. В PHP 8.2 — TypeError. На servermall это проявилось в нескольких шаблонах:
-
Шаблоны шапки и навигации — сравнение товаров (
$curCompare) и избранное ($curWishlist). Значения приходили из кук, и при первом заходе былиnull, а не пустым массивом. Решение:count((array)$curCompare). -
Модификатор результата в карточке товара — свойство сетевой карты могло быть строкой вместо массива при определённых настройках инфоблока. Решение: проверка
is_array()и fallback на пустой массив. -
Шаблон сравнения товаров — несколько свойств (RAID-контроллер, форм-фактор, сетевая карта, тип подключения, типы дисков и др.) использовались в
implode()без проверки типа. Добавилиis_array()перед каждымimplode().
3. Short open tags
Скрипт, отвечающий за добавление конфигурации сервера в корзину, использовал <? вместо <?php. На PHP 7.4 это работало при short_open_tag = On, в 8.2 — белый экран. Замена заняла 30 секунд, но найти скрипт среди сотен файлов — дольше.
4. define() без кавычек
В файле инициализации константа для reCAPTCHA определялась как define(CONSTANT_NAME, value) — без кавычек вокруг имени. PHP 7.4 интерпретировал имя как строку, PHP 8.2 пытался найти константу с таким именем, не находил и выдавал fatal error. Исправление: define('CONSTANT_NAME', value).
5. Проблемы с высоконагруженными блоками (Highload-блоки)
Модуль интеграции с CRM использовал ORM-таблицу со старым именем. При миграции на PHP 8.2 возникли проблемы с совместимостью — пришлось переименовать таблицу, а функциональность временно закомментирована в подвале сайта с пометкой «TODO: Проблема с базой». Это типичный случай, когда миграция PHP вскрывает архитектурные проблемы, не связанные напрямую с версией языка.
6. Вскрывшиеся баги из-за stricter typing — и почему это хорошо
Одно из главных преимуществ PHP 8 — stricter typing перестаёт прощать ошибки, которые PHP 7 молча глотал. Для кода, написанного без типов, это боль. Для кода, где и так использовались тайп-хинты и строгие проверки — это бесплатная проверка качества.
На servermall мы нашли несколько багов, которые PHP 8.2 подсветил сам:
- В компоненте списка характеристик переменная с полем сортировки была перепутана с переменной времени кеширования — типичная copy-paste ошибка. На 7.4 она не проявлялась:
initCache()проглатывал строку вместо числа и работал с настройками по умолчанию. На 8.2 метод потребовалint— и баг вылез. - В шаблоне сравнения товаров свойства передавались в
implode()без проверки, что это массив. Для большинства товаров работало, но для некоторых инфоблоков свойство приходило строкой — иimplode()молча возвращал эту же строку на 7.4, а на 8.2 начал ронять страницу. Проблема существовала годами, просто никто не замечал.
Главный урок: если вы на 7.4 уже пишете с типами, переход на 8.2 — это не исправление тысяч ошибок, а точечная правка нескольких десятков файлов, где типов не было. В нашем случае из ~120 файлов в /local/ реально сломались около двух десятков — остальные переехали без изменений именно потому, что в них уже были тайп-хинты, declare(strict_types=1) и явные проверки типов.
7. Сторонние модули маркетплейса
Один из сторонних модулей SEO-оптимизации содержал старые конструкторы класса (метод с именем класса вместо __construct()). Это десятки файлов в языковых директориях. К счастью, на момент миграции модуль уже получил обновление, и проблема решилась стандартным обновлением через Marketplace.
Другой сторонний модуль для работы со справочниками — в одном из файлов тоже обнаружились проблемы со статическими вызовами.
Процесс миграции: как мы это делали
Хронология работ:
-
Отдельная ветка для миграции — ответвили от dev, чтобы не блокировать текущую разработку. Это оказалось палкой о двух концах: пока мы чинили совместимость с PHP 8.2, остальная команда продолжала пушить в dev новые фичи и правки. Приходилось регулярно сливать изменения из dev в миграционную ветку, и почти каждый такой мёрж что-то ломал — то конфликт в шаблонах, то новый код, написанный без оглядки на 8.2. Держать две ветки в синхронизации было едва ли не сложнее, чем сам переход на PHP.
-
Тестовая копия сайта — полная копия базы и файлов на отдельном окружении с PHP 8.2.
-
Методичный обход ошибок — включали
display_errors = Onв файле настроек, открывали страницу за страницей, читали трейс, фиксили, шли дальше. Никакой магии — просто последовательная работа. -
Приоритезация — сначала критические ошибки (белый экран на главной и в каталоге), потом предупреждения, потом косметика.
-
Особое внимание к
/local/— всё, что в этой директории, требует ручной проверки. Штатное ядро Битрикса к тому моменту уже было совместимо с PHP 8.2, а вот самописный код — нет. -
Комментирование проблемных участков — когда функциональность нельзя починить быстро (как с AmoCRM), временно отключали с комментарием
TODOи номером задачи, чтобы не тормозить весь процесс. -
Ревью изменений — каждый починенный файл проверяли на регрессии: не сломала ли правка что-то ещё.
Типичные ошибки при миграции PHP на сайтах под Битриксом
За годы работы с 1С-Битрикс мы накопили список типовых граблей. Вот что чаще всего идёт не так:
Обновление PHP до обновления модулей. Классика: админ просит хостера поднять версию PHP, сайт падает, выясняется что модули маркетплейса не обновлены. Правильный порядок: сначала обновить ядро и все модули на старой версии PHP, потом менять PHP.
Игнорирование сторонних модулей. Модуль с истёкшей лицензией не получает обновлений. При переходе на PHP 8 он может уронить весь сайт. Проверьте статус лицензий до миграции.
Пропуск тестового окружения. Мигрировать на боевом сервере без предварительной проверки — лотерея. Даже если сайт кажется простым, всегда найдётся скрипт, написанный практикантом в 2014 году, который использовал <? и each().
Недооценка объёма легаси в /local/. На servermall самописного кода оказалось больше, чем ожидалось — около 50 файлов потребовали правок. Чем старше сайт, тем больше сюрпризов.
Отсутствие резервной копии. Банально, но перед любым обновлением PHP делайте полный бэкап файлов и базы. Откат на старую версию PHP не всегда помогает, если данные уже повреждены.
Сравнение с альтернативными подходами
Можно было пойти другим путём — не чинить легаси, а переписать сайт с нуля на современном стеке. Для servermall такой вариант не рассматривался: каталог из тысяч товаров со сложной логикой ценообразования, интеграции с AmoCRM, B2B-личный кабинет — переписывать это означало бы остановить развитие на полгода минимум.
Альтернатива «оставить как есть и надеяться» — тоже не вариант. PHP 7.4 не получает исправлений безопасности, а после февраля 2026 года Битрикс перестанет поддерживать такую конфигурацию. Это значит — ни обновлений ядра, ни новых модулей маркетплейса.
Третий путь — переезд на облачный Битрикс24 — решил бы проблему апдейтов PHP, но не подходит для интернет-магазина с глубокой кастомизацией: облачная версия не даёт такого уровня контроля над кодом.
Миграция PHP «на месте» — самый прагматичный путь для зрелых сайтов на 1С-Битрикс с большим объёмом кастомного кода.
Результаты: что дал переход
После завершения миграции:
- Версия PHP на боевом сервере поднята с 7.4 до 8.2.
- Все критические ошибки исправлены в 18 файлах, затронувших ключевые сценарии: каталог, корзину, сравнение, избранное, авторизацию и конфигуратор.
- Производительность выросла незначительно (PHP 8.2 сам по себе быстрее 7.4 на 10-18% по бенчмаркам), но главный результат — сайт снова получает обновления безопасности и совместим с актуальными версиями модулей.
- Попутно вскрылись и были исправлены несколько багов, годами живших в коде — stricter typing в PHP 8.2 сработал как бесплатный статический анализатор.
Выводы: миграция PHP на сайтах 1С-Битрикс — кому и когда пора обновляться
Переход с PHP 7.4 на 8.2 на сайте под 1С-Битрикс — задача трудоёмкая, но решаемая. Главный вывод: основной объём проблем возникает не в ядре Битрикса (оно к 2025 году уже полностью совместимо с PHP 8.x), а в самописном коде и старых модулях маркетплейса.
Если ваш сайт работает на Битриксе и до сих пор на PHP 7.4 — не откладывайте миграцию. С февраля 2026 года вы не сможете устанавливать обновления. Начните с аудита директории /local/ — посчитайте количество PHP-файлов, оцените возраст кода по коммитам, проверьте лицензии сторонних модулей. Затем поднимите тестовую копию на PHP 8.2 и методично пройдите по ошибкам. За неделю-две можно полностью завершить миграцию даже для крупного проекта.
Проект servermall после перехода стабильно работает на PHP 8.2 — сайт принимает заказы, конфигуратор собирает серверы, личный кабинет обслуживает B2B-клиентов. А самое приятное — apt upgrade снова делает только то, что должен: обновляет пакеты, а не ломает сайт.