[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fX7_0fCF-VlAKy6nvF2wbM9pKloP071sSNsKUIpyeQIQ":3},{"slug":4,"title":5,"published":6,"publishedAt":7,"createdAt":8,"section":9,"preview":10,"heroImage":11,"previewImage":12,"headMarkup":13,"bodyMd":14,"bodyHtml":15},"perehod-saita-bitriks-php74-na-php82-opyt","Как мы перевели сайт на 1С-Битрикс с PHP 7.4 на 8.2: разбор легаси-кода и неочевидных ошибок",true,"2025-05-20T12:00:00+03:00","2026-07-17T19:43:27.772Z","Статьи","С февраля 2026 года 1С-Битрикс ограничивает поддержку продуктов на версиях PHP ниже 8.2. Разбор реального опыта миграции крупного интернет-магазина с PHP 7.4...",null,"\u002Fcontent-media\u002Farticles\u002Fperehod-saita-bitriks-php74-na-php82-opyt\u002Fassets\u002Fpreview.svg",[],"# Как мы перевели сайт на 1С-Битрикс с PHP 7.4 на 8.2: разбор легаси-кода и неочевидных ошибок\n\n## Введение: почему переход на PHP 8.2 стал необходимостью для сайта на Битриксе\n\nС февраля 2026 года 1С-Битрикс ограничивает поддержку продуктов на версиях PHP ниже 8.2. Но проблема не только в формальных сроках — PHP 7.4 перестал получать обновления безопасности ещё в ноябре 2022 года. Четыре года без исправлений уязвимостей — это риск, который не можешь игнорировать, если сайт принимает платежи и обрабатывает персональные данные клиентов.\n\nДля servermall — крупного интернет-магазина серверного оборудования на 1С-Битрикс: Управление сайтом — вопрос стоял остро. Сайт существует с 2012 года, за это время накопился внушительный объём самописного кода: кастомные компоненты, обработчики событий, интеграция с AmoCRM, конфигураторы серверов, фильтры — всё в директории `\u002Flocal\u002F`. Штатные модули маркетплейса тоже добавили сложности: часть решений не обновлялась годами, у некоторых истекли лицензии, а документация давно не актуальна.\n\nВ этой статье — практический разбор перехода: что сломалось при смене версии PHP, какие паттерны ошибок повторялись, как мы их фиксили и что стоит проверить до запуска `apt install php8.2`.\n\n## Контекст проекта\n\nСайт servermall работает на редакции «1С-Битрикс: Управление сайтом — Бизнес». Каталог из нескольких тысяч товаров, конфигураторы сборки серверов, личный кабинет B2B, интеграция с AmoCRM через кастомный модуль в `\u002Flocal\u002F`.\n\nТехнический стек на момент начала миграции: PHP 7.4, MySQL 5.7, веб-сервер Apache с nginx-прокси. В директории `\u002Flocal\u002F` около 120 PHP-файлов с бизнес-логикой, написанной в разное время разными разработчиками. Часть кода — наследие эпохи PHP 5.6, которое просто работало на 7.4 за счёт мягкой политики обратной совместимости.\n\nПри этом с определённого момента мы ввели правило: весь новый код пишем со строгими типами. Объявления `declare(strict_types=1)`, тайп-хинты на аргументах и возвращаемых значениях, явные приведения вместо надежды на неявное — это вошло в практику задолго до PHP 8. Старый код переписывали постепенно, по мере касания. Такая дисциплина сильно сузила фронт работ при миграции: файлы, написанные по-человечески, переезжали на 8.2 без единого изменения.\n\nЗадача на миграцию — №11512 в корпоративном портале, поставлена в октябре 2024 года. Ответственный — Дмитрий Глаголев, основную работу по исправлению кода выполнил Алексей Плотников.\n\n## Что изменилось в PHP 8.x: ключевые несовместимости\n\nПереход с 7.4 сразу на 8.2 — это прыжок через две мажорные версии (8.0 и 8.1). Главное изменение — не синтаксис, а философия: PHP перестал прощать нестрогую типизацию. Если на 7.4 можно было передать строку туда, где ожидается число, и интерпретатор молча делал приведение, то 8.2 либо выбрасывает TypeError, либо ведёт себя иначе. Вот что перестало работать из коробки:\n\n- **Обращение к нестатическим методам как к статическим** — PHP 8.0 превратил notice в фатальную ошибку. Весь код вида `SomeClass::nonStaticMethod()` начал падать.\n- **Передача не-массива в `count()`** — PHP 8.1 выбрасывает TypeError. Если переменная может быть `null` или числом — нужна проверка `is_countable()` или явное приведение к массиву.\n- **Передача не-массива в `implode()`** — аналогично: `implode(', ', $value)` падает, если `$value` не массив. Приходится оборачивать в проверки.\n- **Конструкторы классов** — PHP 8.0 убрал поддержку методов с именем класса в качестве конструктора. Старые модули маркетплейса, написанные до 2016 года, использовали этот подход.\n- **Short open tags `\u003C?`** — директива `short_open_tag` по умолчанию выключена в PHP 8. Если в шаблонах или скриптах встречается `\u003C?` вместо `\u003C?php` — белый экран.\n- **`define()` без кавычек** — `define(CONSTANT_NAME, value)` вместо `define('CONSTANT_NAME', value)`. В PHP 7 прокатывало, в 8 — fatal error.\n- **Ужесточение типов в выражениях** — арифметика с нечисловыми значениями, конкатенация без явного приведения, доступ к индексам не-массивов — всё это либо перестало работать, либо начало выдавать TypeError.\n\n## Что сломалось на servermall: разбор по категориям\n\nМы выкатили PHP 8.2 на тестовую копию сайта и методично фиксили ошибки. Всего потребовалось изменить около 50 PHP-файлов. Все исправления собирались в отдельной ветке, ответвлённой от dev — чтобы не тормозить основные разработки. Разберём по категориям.\n\n### 1. Нестатические методы, вызываемые статически\n\nСамая частая категория. В файле с обработчиками авторизации метод `OnBeforeUserLoginHandler` вызывался ядром Битрикса через `ExecuteModuleEventEx`, но не имел модификатора `static`. PHP 8.2 падал с ошибкой: «Non-static method cannot be called statically».\n\nИсправление — добавить `static`:\n\n```php\n\u002F\u002F Было\nfunction OnBeforeUserLoginHandler(&$arFields) {\n\n\u002F\u002F Стало\nstatic function OnBeforeUserLoginHandler(&$arFields) {\n```\n\nАналогичная ситуация в файле с основными обработчиками — метод `setAdWordsTags()` класса для рекламных меток вызывался статически, но был объявлен как `public function`. Добавили `static public function`.\n\n### 2. `count()` и `implode()` на потенциально не-массивах\n\nВ PHP 7.4 код вроде `count($curCompare)` молча возвращал 0, если `$curCompare` был `null` или `false`. В PHP 8.2 — TypeError. На servermall это проявилось в нескольких шаблонах:\n\n- Шаблоны шапки и навигации — сравнение товаров (`$curCompare`) и избранное (`$curWishlist`). Значения приходили из кук, и при первом заходе были `null`, а не пустым массивом. Решение: `count((array)$curCompare)`.\n\n- Модификатор результата в карточке товара — свойство сетевой карты могло быть строкой вместо массива при определённых настройках инфоблока. Решение: проверка `is_array()` и fallback на пустой массив.\n\n- Шаблон сравнения товаров — несколько свойств (RAID-контроллер, форм-фактор, сетевая карта, тип подключения, типы дисков и др.) использовались в `implode()` без проверки типа. Добавили `is_array()` перед каждым `implode()`.\n\n### 3. Short open tags\n\nСкрипт, отвечающий за добавление конфигурации сервера в корзину, использовал `\u003C?` вместо `\u003C?php`. На PHP 7.4 это работало при `short_open_tag = On`, в 8.2 — белый экран. Замена заняла 30 секунд, но найти скрипт среди сотен файлов — дольше.\n\n### 4. `define()` без кавычек\n\nВ файле инициализации константа для reCAPTCHA определялась как `define(CONSTANT_NAME, value)` — без кавычек вокруг имени. PHP 7.4 интерпретировал имя как строку, PHP 8.2 пытался найти константу с таким именем, не находил и выдавал fatal error. Исправление: `define('CONSTANT_NAME', value)`.\n\n### 5. Проблемы с высоконагруженными блоками (Highload-блоки)\n\nМодуль интеграции с CRM использовал ORM-таблицу со старым именем. При миграции на PHP 8.2 возникли проблемы с совместимостью — пришлось переименовать таблицу, а функциональность временно закомментирована в подвале сайта с пометкой «TODO: Проблема с базой». Это типичный случай, когда миграция PHP вскрывает архитектурные проблемы, не связанные напрямую с версией языка.\n\n### 6. Вскрывшиеся баги из-за stricter typing — и почему это хорошо\n\nОдно из главных преимуществ PHP 8 — stricter typing перестаёт прощать ошибки, которые PHP 7 молча глотал. Для кода, написанного без типов, это боль. Для кода, где и так использовались тайп-хинты и строгие проверки — это бесплатная проверка качества.\n\nНа servermall мы нашли несколько багов, которые PHP 8.2 подсветил сам:\n\n- В компоненте списка характеристик переменная с полем сортировки была перепутана с переменной времени кеширования — типичная copy-paste ошибка. На 7.4 она не проявлялась: `initCache()` проглатывал строку вместо числа и работал с настройками по умолчанию. На 8.2 метод потребовал `int` — и баг вылез.\n- В шаблоне сравнения товаров свойства передавались в `implode()` без проверки, что это массив. Для большинства товаров работало, но для некоторых инфоблоков свойство приходило строкой — и `implode()` молча возвращал эту же строку на 7.4, а на 8.2 начал ронять страницу. Проблема существовала годами, просто никто не замечал.\n\nГлавный урок: если вы на 7.4 уже пишете с типами, переход на 8.2 — это не исправление тысяч ошибок, а точечная правка нескольких десятков файлов, где типов не было. В нашем случае из ~120 файлов в `\u002Flocal\u002F` реально сломались около двух десятков — остальные переехали без изменений именно потому, что в них уже были тайп-хинты, `declare(strict_types=1)` и явные проверки типов.\n\n### 7. Сторонние модули маркетплейса\n\nОдин из сторонних модулей SEO-оптимизации содержал старые конструкторы класса (метод с именем класса вместо `__construct()`). Это десятки файлов в языковых директориях. К счастью, на момент миграции модуль уже получил обновление, и проблема решилась стандартным обновлением через Marketplace.\n\nДругой сторонний модуль для работы со справочниками — в одном из файлов тоже обнаружились проблемы со статическими вызовами.\n\n## Процесс миграции: как мы это делали\n\nХронология работ:\n\n1. **Отдельная ветка для миграции** — ответвили от dev, чтобы не блокировать текущую разработку. Это оказалось палкой о двух концах: пока мы чинили совместимость с PHP 8.2, остальная команда продолжала пушить в dev новые фичи и правки. Приходилось регулярно сливать изменения из dev в миграционную ветку, и почти каждый такой мёрж что-то ломал — то конфликт в шаблонах, то новый код, написанный без оглядки на 8.2. Держать две ветки в синхронизации было едва ли не сложнее, чем сам переход на PHP.\n\n2. **Тестовая копия сайта** — полная копия базы и файлов на отдельном окружении с PHP 8.2.\n\n3. **Методичный обход ошибок** — включали `display_errors = On` в файле настроек, открывали страницу за страницей, читали трейс, фиксили, шли дальше. Никакой магии — просто последовательная работа.\n\n4. **Приоритезация** — сначала критические ошибки (белый экран на главной и в каталоге), потом предупреждения, потом косметика.\n\n5. **Особое внимание к `\u002Flocal\u002F`** — всё, что в этой директории, требует ручной проверки. Штатное ядро Битрикса к тому моменту уже было совместимо с PHP 8.2, а вот самописный код — нет.\n\n6. **Комментирование проблемных участков** — когда функциональность нельзя починить быстро (как с AmoCRM), временно отключали с комментарием `TODO` и номером задачи, чтобы не тормозить весь процесс.\n\n7. **Ревью изменений** — каждый починенный файл проверяли на регрессии: не сломала ли правка что-то ещё.\n\n## Типичные ошибки при миграции PHP на сайтах под Битриксом\n\nЗа годы работы с 1С-Битрикс мы накопили список типовых граблей. Вот что чаще всего идёт не так:\n\n**Обновление PHP до обновления модулей.** Классика: админ просит хостера поднять версию PHP, сайт падает, выясняется что модули маркетплейса не обновлены. Правильный порядок: сначала обновить ядро и все модули на старой версии PHP, потом менять PHP.\n\n**Игнорирование сторонних модулей.** Модуль с истёкшей лицензией не получает обновлений. При переходе на PHP 8 он может уронить весь сайт. Проверьте статус лицензий до миграции.\n\n**Пропуск тестового окружения.** Мигрировать на боевом сервере без предварительной проверки — лотерея. Даже если сайт кажется простым, всегда найдётся скрипт, написанный практикантом в 2014 году, который использовал `\u003C?` и `each()`.\n\n**Недооценка объёма легаси в `\u002Flocal\u002F`.** На servermall самописного кода оказалось больше, чем ожидалось — около 50 файлов потребовали правок. Чем старше сайт, тем больше сюрпризов.\n\n**Отсутствие резервной копии.** Банально, но перед любым обновлением PHP делайте полный бэкап файлов и базы. Откат на старую версию PHP не всегда помогает, если данные уже повреждены.\n\n## Сравнение с альтернативными подходами\n\nМожно было пойти другим путём — не чинить легаси, а переписать сайт с нуля на современном стеке. Для servermall такой вариант не рассматривался: каталог из тысяч товаров со сложной логикой ценообразования, интеграции с AmoCRM, B2B-личный кабинет — переписывать это означало бы остановить развитие на полгода минимум.\n\nАльтернатива «оставить как есть и надеяться» — тоже не вариант. PHP 7.4 не получает исправлений безопасности, а после февраля 2026 года Битрикс перестанет поддерживать такую конфигурацию. Это значит — ни обновлений ядра, ни новых модулей маркетплейса.\n\nТретий путь — переезд на облачный Битрикс24 — решил бы проблему апдейтов PHP, но не подходит для интернет-магазина с глубокой кастомизацией: облачная версия не даёт такого уровня контроля над кодом.\n\nМиграция PHP «на месте» — самый прагматичный путь для зрелых сайтов на 1С-Битрикс с большим объёмом кастомного кода.\n\n## Результаты: что дал переход\n\nПосле завершения миграции:\n\n- Версия PHP на боевом сервере поднята с 7.4 до 8.2.\n- Все критические ошибки исправлены в 18 файлах, затронувших ключевые сценарии: каталог, корзину, сравнение, избранное, авторизацию и конфигуратор.\n- Производительность выросла незначительно (PHP 8.2 сам по себе быстрее 7.4 на 10-18% по бенчмаркам), но главный результат — сайт снова получает обновления безопасности и совместим с актуальными версиями модулей.\n- Попутно вскрылись и были исправлены несколько багов, годами живших в коде — stricter typing в PHP 8.2 сработал как бесплатный статический анализатор.\n\n## Выводы: миграция PHP на сайтах 1С-Битрикс — кому и когда пора обновляться\n\nПереход с PHP 7.4 на 8.2 на сайте под 1С-Битрикс — задача трудоёмкая, но решаемая. Главный вывод: основной объём проблем возникает не в ядре Битрикса (оно к 2025 году уже полностью совместимо с PHP 8.x), а в самописном коде и старых модулях маркетплейса.\n\nЕсли ваш сайт работает на Битриксе и до сих пор на PHP 7.4 — не откладывайте миграцию. С февраля 2026 года вы не сможете устанавливать обновления. Начните с аудита директории `\u002Flocal\u002F` — посчитайте количество PHP-файлов, оцените возраст кода по коммитам, проверьте лицензии сторонних модулей. Затем поднимите тестовую копию на PHP 8.2 и методично пройдите по ошибкам. За неделю-две можно полностью завершить миграцию даже для крупного проекта.\n\nПроект servermall после перехода стабильно работает на PHP 8.2 — сайт принимает заказы, конфигуратор собирает серверы, личный кабинет обслуживает B2B-клиентов. А самое приятное — `apt upgrade` снова делает только то, что должен: обновляет пакеты, а не ломает сайт.","\u003Ch1>Как мы перевели сайт на 1С-Битрикс с PHP 7.4 на 8.2: разбор легаси-кода и неочевидных ошибок\u003C\u002Fh1>\n\u003Ch2>Введение: почему переход на PHP 8.2 стал необходимостью для сайта на Битриксе\u003C\u002Fh2>\n\u003Cp>С февраля 2026 года 1С-Битрикс ограничивает поддержку продуктов на версиях PHP ниже 8.2. Но проблема не только в формальных сроках — PHP 7.4 перестал получать обновления безопасности ещё в ноябре 2022 года. Четыре года без исправлений уязвимостей — это риск, который не можешь игнорировать, если сайт принимает платежи и обрабатывает персональные данные клиентов.\u003C\u002Fp>\n\u003Cp>Для servermall — крупного интернет-магазина серверного оборудования на 1С-Битрикс: Управление сайтом — вопрос стоял остро. Сайт существует с 2012 года, за это время накопился внушительный объём самописного кода: кастомные компоненты, обработчики событий, интеграция с AmoCRM, конфигураторы серверов, фильтры — всё в директории \u003Ccode>\u002Flocal\u002F\u003C\u002Fcode>. Штатные модули маркетплейса тоже добавили сложности: часть решений не обновлялась годами, у некоторых истекли лицензии, а документация давно не актуальна.\u003C\u002Fp>\n\u003Cp>В этой статье — практический разбор перехода: что сломалось при смене версии PHP, какие паттерны ошибок повторялись, как мы их фиксили и что стоит проверить до запуска \u003Ccode>apt install php8.2\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch2>Контекст проекта\u003C\u002Fh2>\n\u003Cp>Сайт servermall работает на редакции «1С-Битрикс: Управление сайтом — Бизнес». Каталог из нескольких тысяч товаров, конфигураторы сборки серверов, личный кабинет B2B, интеграция с AmoCRM через кастомный модуль в \u003Ccode>\u002Flocal\u002F\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>Технический стек на момент начала миграции: PHP 7.4, MySQL 5.7, веб-сервер Apache с nginx-прокси. В директории \u003Ccode>\u002Flocal\u002F\u003C\u002Fcode> около 120 PHP-файлов с бизнес-логикой, написанной в разное время разными разработчиками. Часть кода — наследие эпохи PHP 5.6, которое просто работало на 7.4 за счёт мягкой политики обратной совместимости.\u003C\u002Fp>\n\u003Cp>При этом с определённого момента мы ввели правило: весь новый код пишем со строгими типами. Объявления \u003Ccode>declare(strict_types=1)\u003C\u002Fcode>, тайп-хинты на аргументах и возвращаемых значениях, явные приведения вместо надежды на неявное — это вошло в практику задолго до PHP 8. Старый код переписывали постепенно, по мере касания. Такая дисциплина сильно сузила фронт работ при миграции: файлы, написанные по-человечески, переезжали на 8.2 без единого изменения.\u003C\u002Fp>\n\u003Cp>Задача на миграцию — №11512 в корпоративном портале, поставлена в октябре 2024 года. Ответственный — Дмитрий Глаголев, основную работу по исправлению кода выполнил Алексей Плотников.\u003C\u002Fp>\n\u003Ch2>Что изменилось в PHP 8.x: ключевые несовместимости\u003C\u002Fh2>\n\u003Cp>Переход с 7.4 сразу на 8.2 — это прыжок через две мажорные версии (8.0 и 8.1). Главное изменение — не синтаксис, а философия: PHP перестал прощать нестрогую типизацию. Если на 7.4 можно было передать строку туда, где ожидается число, и интерпретатор молча делал приведение, то 8.2 либо выбрасывает TypeError, либо ведёт себя иначе. Вот что перестало работать из коробки:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Обращение к нестатическим методам как к статическим\u003C\u002Fstrong> — PHP 8.0 превратил notice в фатальную ошибку. Весь код вида \u003Ccode>SomeClass::nonStaticMethod()\u003C\u002Fcode> начал падать.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Передача не-массива в \u003Ccode>count()\u003C\u002Fcode>\u003C\u002Fstrong> — PHP 8.1 выбрасывает TypeError. Если переменная может быть \u003Ccode>null\u003C\u002Fcode> или числом — нужна проверка \u003Ccode>is_countable()\u003C\u002Fcode> или явное приведение к массиву.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Передача не-массива в \u003Ccode>implode()\u003C\u002Fcode>\u003C\u002Fstrong> — аналогично: \u003Ccode>implode(', ', $value)\u003C\u002Fcode> падает, если \u003Ccode>$value\u003C\u002Fcode> не массив. Приходится оборачивать в проверки.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Конструкторы классов\u003C\u002Fstrong> — PHP 8.0 убрал поддержку методов с именем класса в качестве конструктора. Старые модули маркетплейса, написанные до 2016 года, использовали этот подход.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Short open tags \u003Ccode>&lt;?\u003C\u002Fcode>\u003C\u002Fstrong> — директива \u003Ccode>short_open_tag\u003C\u002Fcode> по умолчанию выключена в PHP 8. Если в шаблонах или скриптах встречается \u003Ccode>&lt;?\u003C\u002Fcode> вместо \u003Ccode>&lt;?php\u003C\u002Fcode> — белый экран.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>define()\u003C\u002Fcode> без кавычек\u003C\u002Fstrong> — \u003Ccode>define(CONSTANT_NAME, value)\u003C\u002Fcode> вместо \u003Ccode>define('CONSTANT_NAME', value)\u003C\u002Fcode>. В PHP 7 прокатывало, в 8 — fatal error.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Ужесточение типов в выражениях\u003C\u002Fstrong> — арифметика с нечисловыми значениями, конкатенация без явного приведения, доступ к индексам не-массивов — всё это либо перестало работать, либо начало выдавать TypeError.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Что сломалось на servermall: разбор по категориям\u003C\u002Fh2>\n\u003Cp>Мы выкатили PHP 8.2 на тестовую копию сайта и методично фиксили ошибки. Всего потребовалось изменить около 50 PHP-файлов. Все исправления собирались в отдельной ветке, ответвлённой от dev — чтобы не тормозить основные разработки. Разберём по категориям.\u003C\u002Fp>\n\u003Ch3>1. Нестатические методы, вызываемые статически\u003C\u002Fh3>\n\u003Cp>Самая частая категория. В файле с обработчиками авторизации метод \u003Ccode>OnBeforeUserLoginHandler\u003C\u002Fcode> вызывался ядром Битрикса через \u003Ccode>ExecuteModuleEventEx\u003C\u002Fcode>, но не имел модификатора \u003Ccode>static\u003C\u002Fcode>. PHP 8.2 падал с ошибкой: «Non-static method cannot be called statically».\u003C\u002Fp>\n\u003Cp>Исправление — добавить \u003Ccode>static\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">\u002F\u002F Было\nfunction OnBeforeUserLoginHandler(&amp;$arFields) {\n\n\u002F\u002F Стало\nstatic function OnBeforeUserLoginHandler(&amp;$arFields) {\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Аналогичная ситуация в файле с основными обработчиками — метод \u003Ccode>setAdWordsTags()\u003C\u002Fcode> класса для рекламных меток вызывался статически, но был объявлен как \u003Ccode>public function\u003C\u002Fcode>. Добавили \u003Ccode>static public function\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch3>2. \u003Ccode>count()\u003C\u002Fcode> и \u003Ccode>implode()\u003C\u002Fcode> на потенциально не-массивах\u003C\u002Fh3>\n\u003Cp>В PHP 7.4 код вроде \u003Ccode>count($curCompare)\u003C\u002Fcode> молча возвращал 0, если \u003Ccode>$curCompare\u003C\u002Fcode> был \u003Ccode>null\u003C\u002Fcode> или \u003Ccode>false\u003C\u002Fcode>. В PHP 8.2 — TypeError. На servermall это проявилось в нескольких шаблонах:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\n\u003Cp>Шаблоны шапки и навигации — сравнение товаров (\u003Ccode>$curCompare\u003C\u002Fcode>) и избранное (\u003Ccode>$curWishlist\u003C\u002Fcode>). Значения приходили из кук, и при первом заходе были \u003Ccode>null\u003C\u002Fcode>, а не пустым массивом. Решение: \u003Ccode>count((array)$curCompare)\u003C\u002Fcode>.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>Модификатор результата в карточке товара — свойство сетевой карты могло быть строкой вместо массива при определённых настройках инфоблока. Решение: проверка \u003Ccode>is_array()\u003C\u002Fcode> и fallback на пустой массив.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>Шаблон сравнения товаров — несколько свойств (RAID-контроллер, форм-фактор, сетевая карта, тип подключения, типы дисков и др.) использовались в \u003Ccode>implode()\u003C\u002Fcode> без проверки типа. Добавили \u003Ccode>is_array()\u003C\u002Fcode> перед каждым \u003Ccode>implode()\u003C\u002Fcode>.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>3. Short open tags\u003C\u002Fh3>\n\u003Cp>Скрипт, отвечающий за добавление конфигурации сервера в корзину, использовал \u003Ccode>&lt;?\u003C\u002Fcode> вместо \u003Ccode>&lt;?php\u003C\u002Fcode>. На PHP 7.4 это работало при \u003Ccode>short_open_tag = On\u003C\u002Fcode>, в 8.2 — белый экран. Замена заняла 30 секунд, но найти скрипт среди сотен файлов — дольше.\u003C\u002Fp>\n\u003Ch3>4. \u003Ccode>define()\u003C\u002Fcode> без кавычек\u003C\u002Fh3>\n\u003Cp>В файле инициализации константа для reCAPTCHA определялась как \u003Ccode>define(CONSTANT_NAME, value)\u003C\u002Fcode> — без кавычек вокруг имени. PHP 7.4 интерпретировал имя как строку, PHP 8.2 пытался найти константу с таким именем, не находил и выдавал fatal error. Исправление: \u003Ccode>define('CONSTANT_NAME', value)\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch3>5. Проблемы с высоконагруженными блоками (Highload-блоки)\u003C\u002Fh3>\n\u003Cp>Модуль интеграции с CRM использовал ORM-таблицу со старым именем. При миграции на PHP 8.2 возникли проблемы с совместимостью — пришлось переименовать таблицу, а функциональность временно закомментирована в подвале сайта с пометкой «TODO: Проблема с базой». Это типичный случай, когда миграция PHP вскрывает архитектурные проблемы, не связанные напрямую с версией языка.\u003C\u002Fp>\n\u003Ch3>6. Вскрывшиеся баги из-за stricter typing — и почему это хорошо\u003C\u002Fh3>\n\u003Cp>Одно из главных преимуществ PHP 8 — stricter typing перестаёт прощать ошибки, которые PHP 7 молча глотал. Для кода, написанного без типов, это боль. Для кода, где и так использовались тайп-хинты и строгие проверки — это бесплатная проверка качества.\u003C\u002Fp>\n\u003Cp>На servermall мы нашли несколько багов, которые PHP 8.2 подсветил сам:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>В компоненте списка характеристик переменная с полем сортировки была перепутана с переменной времени кеширования — типичная copy-paste ошибка. На 7.4 она не проявлялась: \u003Ccode>initCache()\u003C\u002Fcode> проглатывал строку вместо числа и работал с настройками по умолчанию. На 8.2 метод потребовал \u003Ccode>int\u003C\u002Fcode> — и баг вылез.\u003C\u002Fli>\n\u003Cli>В шаблоне сравнения товаров свойства передавались в \u003Ccode>implode()\u003C\u002Fcode> без проверки, что это массив. Для большинства товаров работало, но для некоторых инфоблоков свойство приходило строкой — и \u003Ccode>implode()\u003C\u002Fcode> молча возвращал эту же строку на 7.4, а на 8.2 начал ронять страницу. Проблема существовала годами, просто никто не замечал.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Главный урок: если вы на 7.4 уже пишете с типами, переход на 8.2 — это не исправление тысяч ошибок, а точечная правка нескольких десятков файлов, где типов не было. В нашем случае из ~120 файлов в \u003Ccode>\u002Flocal\u002F\u003C\u002Fcode> реально сломались около двух десятков — остальные переехали без изменений именно потому, что в них уже были тайп-хинты, \u003Ccode>declare(strict_types=1)\u003C\u002Fcode> и явные проверки типов.\u003C\u002Fp>\n\u003Ch3>7. Сторонние модули маркетплейса\u003C\u002Fh3>\n\u003Cp>Один из сторонних модулей SEO-оптимизации содержал старые конструкторы класса (метод с именем класса вместо \u003Ccode>__construct()\u003C\u002Fcode>). Это десятки файлов в языковых директориях. К счастью, на момент миграции модуль уже получил обновление, и проблема решилась стандартным обновлением через Marketplace.\u003C\u002Fp>\n\u003Cp>Другой сторонний модуль для работы со справочниками — в одном из файлов тоже обнаружились проблемы со статическими вызовами.\u003C\u002Fp>\n\u003Ch2>Процесс миграции: как мы это делали\u003C\u002Fh2>\n\u003Cp>Хронология работ:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Отдельная ветка для миграции\u003C\u002Fstrong> — ответвили от dev, чтобы не блокировать текущую разработку. Это оказалось палкой о двух концах: пока мы чинили совместимость с PHP 8.2, остальная команда продолжала пушить в dev новые фичи и правки. Приходилось регулярно сливать изменения из dev в миграционную ветку, и почти каждый такой мёрж что-то ломал — то конфликт в шаблонах, то новый код, написанный без оглядки на 8.2. Держать две ветки в синхронизации было едва ли не сложнее, чем сам переход на PHP.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Тестовая копия сайта\u003C\u002Fstrong> — полная копия базы и файлов на отдельном окружении с PHP 8.2.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Методичный обход ошибок\u003C\u002Fstrong> — включали \u003Ccode>display_errors = On\u003C\u002Fcode> в файле настроек, открывали страницу за страницей, читали трейс, фиксили, шли дальше. Никакой магии — просто последовательная работа.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Приоритезация\u003C\u002Fstrong> — сначала критические ошибки (белый экран на главной и в каталоге), потом предупреждения, потом косметика.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Особое внимание к \u003Ccode>\u002Flocal\u002F\u003C\u002Fcode>\u003C\u002Fstrong> — всё, что в этой директории, требует ручной проверки. Штатное ядро Битрикса к тому моменту уже было совместимо с PHP 8.2, а вот самописный код — нет.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Комментирование проблемных участков\u003C\u002Fstrong> — когда функциональность нельзя починить быстро (как с AmoCRM), временно отключали с комментарием \u003Ccode>TODO\u003C\u002Fcode> и номером задачи, чтобы не тормозить весь процесс.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Ревью изменений\u003C\u002Fstrong> — каждый починенный файл проверяли на регрессии: не сломала ли правка что-то ещё.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2>Типичные ошибки при миграции PHP на сайтах под Битриксом\u003C\u002Fh2>\n\u003Cp>За годы работы с 1С-Битрикс мы накопили список типовых граблей. Вот что чаще всего идёт не так:\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Обновление PHP до обновления модулей.\u003C\u002Fstrong> Классика: админ просит хостера поднять версию PHP, сайт падает, выясняется что модули маркетплейса не обновлены. Правильный порядок: сначала обновить ядро и все модули на старой версии PHP, потом менять PHP.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Игнорирование сторонних модулей.\u003C\u002Fstrong> Модуль с истёкшей лицензией не получает обновлений. При переходе на PHP 8 он может уронить весь сайт. Проверьте статус лицензий до миграции.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Пропуск тестового окружения.\u003C\u002Fstrong> Мигрировать на боевом сервере без предварительной проверки — лотерея. Даже если сайт кажется простым, всегда найдётся скрипт, написанный практикантом в 2014 году, который использовал \u003Ccode>&lt;?\u003C\u002Fcode> и \u003Ccode>each()\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Недооценка объёма легаси в \u003Ccode>\u002Flocal\u002F\u003C\u002Fcode>.\u003C\u002Fstrong> На servermall самописного кода оказалось больше, чем ожидалось — около 50 файлов потребовали правок. Чем старше сайт, тем больше сюрпризов.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Отсутствие резервной копии.\u003C\u002Fstrong> Банально, но перед любым обновлением PHP делайте полный бэкап файлов и базы. Откат на старую версию PHP не всегда помогает, если данные уже повреждены.\u003C\u002Fp>\n\u003Ch2>Сравнение с альтернативными подходами\u003C\u002Fh2>\n\u003Cp>Можно было пойти другим путём — не чинить легаси, а переписать сайт с нуля на современном стеке. Для servermall такой вариант не рассматривался: каталог из тысяч товаров со сложной логикой ценообразования, интеграции с AmoCRM, B2B-личный кабинет — переписывать это означало бы остановить развитие на полгода минимум.\u003C\u002Fp>\n\u003Cp>Альтернатива «оставить как есть и надеяться» — тоже не вариант. PHP 7.4 не получает исправлений безопасности, а после февраля 2026 года Битрикс перестанет поддерживать такую конфигурацию. Это значит — ни обновлений ядра, ни новых модулей маркетплейса.\u003C\u002Fp>\n\u003Cp>Третий путь — переезд на облачный Битрикс24 — решил бы проблему апдейтов PHP, но не подходит для интернет-магазина с глубокой кастомизацией: облачная версия не даёт такого уровня контроля над кодом.\u003C\u002Fp>\n\u003Cp>Миграция PHP «на месте» — самый прагматичный путь для зрелых сайтов на 1С-Битрикс с большим объёмом кастомного кода.\u003C\u002Fp>\n\u003Ch2>Результаты: что дал переход\u003C\u002Fh2>\n\u003Cp>После завершения миграции:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Версия PHP на боевом сервере поднята с 7.4 до 8.2.\u003C\u002Fli>\n\u003Cli>Все критические ошибки исправлены в 18 файлах, затронувших ключевые сценарии: каталог, корзину, сравнение, избранное, авторизацию и конфигуратор.\u003C\u002Fli>\n\u003Cli>Производительность выросла незначительно (PHP 8.2 сам по себе быстрее 7.4 на 10-18% по бенчмаркам), но главный результат — сайт снова получает обновления безопасности и совместим с актуальными версиями модулей.\u003C\u002Fli>\n\u003Cli>Попутно вскрылись и были исправлены несколько багов, годами живших в коде — stricter typing в PHP 8.2 сработал как бесплатный статический анализатор.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Выводы: миграция PHP на сайтах 1С-Битрикс — кому и когда пора обновляться\u003C\u002Fh2>\n\u003Cp>Переход с PHP 7.4 на 8.2 на сайте под 1С-Битрикс — задача трудоёмкая, но решаемая. Главный вывод: основной объём проблем возникает не в ядре Битрикса (оно к 2025 году уже полностью совместимо с PHP 8.x), а в самописном коде и старых модулях маркетплейса.\u003C\u002Fp>\n\u003Cp>Если ваш сайт работает на Битриксе и до сих пор на PHP 7.4 — не откладывайте миграцию. С февраля 2026 года вы не сможете устанавливать обновления. Начните с аудита директории \u003Ccode>\u002Flocal\u002F\u003C\u002Fcode> — посчитайте количество PHP-файлов, оцените возраст кода по коммитам, проверьте лицензии сторонних модулей. Затем поднимите тестовую копию на PHP 8.2 и методично пройдите по ошибкам. За неделю-две можно полностью завершить миграцию даже для крупного проекта.\u003C\u002Fp>\n\u003Cp>Проект servermall после перехода стабильно работает на PHP 8.2 — сайт принимает заказы, конфигуратор собирает серверы, личный кабинет обслуживает B2B-клиентов. А самое приятное — \u003Ccode>apt upgrade\u003C\u002Fcode> снова делает только то, что должен: обновляет пакеты, а не ломает сайт.\u003C\u002Fp>\n"]