Один undefined constant в покупном модуле ронял весь сайт на PHP 8.2
После обновления платформы сайт начал отдавать фатальную ошибку на каждой странице — но только новым посетителям. Причина пряталась в покупном модуле с маркетплейса, который обращался к константе ядра, которой в новой версии больше нет. Показываем, как закрыли это правкой в одну строку, не тронув ни ядро, ни сам модуль.
Симптом
Сайт услуг на 1С-Битрикс, собранный на покупном шаблоне с маркетплейса. Главная и внутренние страницы падали в hard fatal — но воспроизводилось это только для новых сессий, у которых гео-данные ещё не заполнены. То есть первый заход нового посетителя = белый экран с ошибкой.
Разведка
Трасса вела из header.php (он на каждой странице подтягивает блок регионов) в компонент регионов и дальше в метод определения региона по IP. Текст ошибки:
Undefined constant Bitrix\Main\Service\GeoIp\Manager::INFO_NOT_AVAILABLE.
Причина
Покупной модуль регионов сравнивал результат определения гео с константой Manager::INFO_NOT_AVAILABLE. В установленной версии ядра (main 26.400) такой константы нет — метод возвращает Result|null. На PHP 8.2 обращение к несуществующей константе класса — это уже не «тихий» null, а фатальная ошибка. Баг вендорского модуля, не ядра, и срабатывал он ровно там, где гео ещё не определено, — у новых посетителей.
Что сделали
Правку вынесли в слой local/, оставив файлы модуля нетронутыми (переживёт его будущие обновления):
- через
init.phpподгрузили патч-копию класса до того, как сработает ленивая автозагрузка модуля; - в копии заменили сравнение с несуществующей константой на честную проверку результата (
if ($result) { ... }) — фактически одна строка; - аккуратно поправили путь загрузки языковых сообщений, чтобы копия из
local/их находила.
Ядро и сам модуль не трогали. Reflection подтвердил, что теперь грузится наша копия класса — даже если вернуть файл модуля в исходное, «сломанное» состояние.
Результат
php -l чист, свежая сессия отдаёт HTTP 200 без единого маркера ошибки. Изменение — буквально одна строка кода, но она вернула сайту работоспособность для всех новых посетителей. Правильное место для фикса чужого бага — не ядро и не файлы модуля, а local/: так обновления не затрут заплатку.
Имя клиента не раскрываем по NDA. Цифры и подход — реальные.