Падение Aspro SmartSEO после обновления Битрикс: разбор причины и корректный фикс сигнатуры getRowById
Обновления ядра 1С-Битрикс нередко выявляют слабые места сторонних модулей. Летом–осенью 2025 года на ряде проектов проявилась критическая ошибка в модуле Aspro SmartSEO, из-за которой сайты начинали отдавать 500-е ошибки, переставал работать каталог, переставали работать SEO-фильтры и связанные страницы.
На первый взгляд проблема выглядит как «очередной баг обновления». На практике — это классический пример нарушения контракта наследования в PHP, который долгое время оставался незаметным и «взорвался» после очередных изменений ORM ядра.
В этой статье:
- разберём реальную причину ошибки, а не симптомы;
- покажем, почему она проявилась именно сейчас;
- приведём корректное и воспроизводимое решение, применённое на рабочем проекте;
- объясним, что именно чинит каждая правка и почему она безопасна.
Симптомы проблемы
После обновления ядра Битрикс сайт начинает падать с фатальной ошибкой PHP. Типичный текст ошибки выглядит так:
Fatal error: Declaration of Aspro\Smartseo\Models\SmartseoFilterRuleTable::getRowById($id)
must be compatible with Bitrix\Main\ORM\Data\DataManager::getRowById($id, array $parameters = [])
Проявления на проекте:
- страницы каталога и умного фильтра возвращают HTTP 500;
- SEO-страницы, сгенерированные SmartSEO, не открываются;
- в логах php_error.log — фатал без возможности graceful fallback;
- кеш не спасает, потому что выполнение падает до логики модуля.
Важно: ошибка возникает не в пользовательском коде, а внутри модуля SmartSEO, поэтому «поправить компонент» или «переустановить шаблон» не помогает.
Почему это происходит на самом деле
Ключевой момент — ORM и наследование
В основе проблемы лежит метод:
Bitrix\Main\ORM\Data\DataManager::getRowById()
В актуальных версиях ядра его сигнатура выглядит так:
public static function getRowById($id, array $parameters = [])
Параметр $parameters используется ORM для передачи дополнительных условий выборки, runtime-полей, select и других параметров запроса.
Что делает Aspro SmartSEO
Модуль SmartSEO содержит собственные ORM-таблицы в пространстве имён:
Aspro\Smartseo\Models\*
Эти классы наследуются от DataManager, но в ряде файлов метод getRowById был переопределён с устаревшей сигнатурой:
public static function getRowById($id)
Это прямое нарушение правил совместимости методов в PHP:
Если метод переопределяется в дочернем классе, его сигнатура должна быть совместима с родительской.
Ранее это не вызывало ошибок либо из-за более мягких проверок, либо из-за того, что код не исполнялся в критических сценариях. После обновления ядра проверка стала строгой — и PHP закономерно завершает выполнение с fatal error.
Почему это не «мелкий баг», а архитектурная ошибка
Здесь важно зафиксировать:
проблема не в обновлении Битрикс.
Ядро действует корректно:
- метод getRowById расширен;
- обратная совместимость соблюдена;
- сигнатура официальная и используется ORM.
Ошибка — в модуле, который:
- наследуется от DataManager;
- переопределяет метод;
- не обновляет сигнатуру под родителя.
Это означает, что ошибка гарантированно будет всплывать и дальше, при любых последующих изменениях ORM.
Корректное решение: патч сигнатуры и вызова родителя
Решение должно делать две вещи:
- Привести сигнатуру метода в дочерних классах к совместимой.
- Корректно прокинуть $parameters в вызов родительского метода.
Важный принцип
Мы не ломаем API, не меняем логику выборки, не добавляем костылей.
Мы всего лишь приводим код модуля в соответствие с контрактом родительского класса.
Шаг 1. Исправление сигнатуры getRowById
Необходимо во всех моделях SmartSEO заменить:
function getRowById($id)
на:
function getRowById($id, array $parameters = [])
Практически и безопасно это делается одной командой, без ручного редактирования файлов:
perl -0777 -i -pe 's/function\s+getRowById\s<i>\(\s</i>\$id\s\*\)/function getRowById(\$id, array \$parameters = [])/g' \
bitrix/modules/aspro.smartseo/lib/models/\*.php
Проверка результата
grep -R "function getRowById" -n bitrix/modules/aspro.smartseo/lib/models/
Ожидаемый вид:
public static function getRowById($id, array $parameters = []) {
Шаг 2. Исправление вызова parent::getRowById
В ряде моделей внутри метода используется вызов:
parent::getRowById($id)
После изменения сигнатуры это уже некорректно, так как $parameters теряются.
Поиск проблемных мест
grep -R "parent::getRowById\s\*(" -n bitrix/modules/aspro.smartseo/lib/models/
Массовый патч
perl -0777 -i -pe 's/parent::getRowById\s<i>\(\s</i>\$id\s\*\)/parent::getRowById(\$id, \$parameters)/g' \
bitrix/modules/aspro.smartseo/lib/models/\*.php
Ожидаемый результат
$data = parent::getRowById($id, $parameters);
Это полностью соответствует контракту ORM и не меняет бизнес-логику модуля.
Шаг 3. Очистка кеша Битрикс
Даже корректный код не заработает, если Битрикс продолжает использовать старые кешированные данные.
Обязательный шаг:
rm -rf bitrix/cache/<i> bitrix/managed\_cache/</i>
После этого фатальные ошибки исчезают, а SmartSEO начинает работать штатно.
Что именно исправляет этот патч
- устраняет фатальную ошибку PHP;
- восстанавливает работу каталога и SEO-страниц;
- делает модуль совместимым с текущей и будущими версиями ORM;
- не влияет на данные, структуру БД и настройки проекта.
Это не временный «костыль», а приведение модуля в корректное состояние.
Почему именно такое решение — правильное
- Соответствует ООП-контракту
Мы не подавляем ошибку, а устраняем её причину.
- Минимальное вмешательство
Меняется только сигнатура и прокидывание параметров.
- Воспроизводимость
Решение можно повторить на любом сервере и проекте.
- Безопасность
Нет влияния на данные, миграции, кеш-ключи, SEO-логику.
Вывод
Ошибка SmartSEO после обновления Битрикс — не «случайный баг», а результат устаревшего кода модуля, который долгое время нарушал контракт ORM.
Обновление ядра лишь сделало проблему видимой.
Правильный подход в таких ситуациях:
- не откатывать ядро;
- не править код вручную «на глаз»;
- не маскировать ошибку.
А приводить сигнатуры методов в соответствие с родительскими классами.
Именно это и делает описанный патч.
Если нужно — дальше можно разобрать, как автоматизировать такие проверки для модулей или как отслеживать подобные несовместимости до выхода в прод. Но это уже отдельная инженерная тема.
Top comments (0)