Рефакторинг старого API на D7 1С-Битрикс
Проекты на Битрикс, которым 5–10 лет, написаны на «старом API»: глобальный $APPLICATION, CIBlockElement::GetList(), $DB->Query() с конкатенацией строк, функции из CModule. Этот код работает — пока. Проблемы начинаются при попытке масштабировать, протестировать или передать другой команде. Рефакторинг на D7 — это не «переписать ради переписки», а снизить стоимость поддержки и исключить класс ошибок, характерных для процедурного кода.
Что именно меняется при переходе на D7
Глобальные функции → методы DataManager:
// Было — старый API
$res = CIBlockElement::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => 5, 'ACTIVE' => 'Y'],
false,
['nPageSize' => 20],
['ID', 'NAME', 'PROPERTY_PRICE']
);
while ($arItem = $res->GetNextElement()) {
$arFields = $arItem->GetFields();
$arProps = $arItem->GetProperties();
}
// Стало — D7 ORM
$result = \Bitrix\Iblock\Elements\ElementProductsTable::getList([
'select' => ['ID', 'NAME', 'PROPERTY_PRICE_VALUE'],
'filter' => ['=IBLOCK_ID' => 5, '=ACTIVE' => 'Y'],
'order' => ['SORT' => 'ASC'],
'limit' => 20,
]);
foreach ($result->fetchCollection() as $element) {
$name = $element->getName();
$price = $element->get('PROPERTY_PRICE_VALUE');
}
SQL-строки → Connection API:
// Было — прямой SQL с конкатенацией
global $DB;
$id = intval($id); // вся «защита»
$res = $DB->Query("SELECT * FROM b_custom_table WHERE ID = " . $id);
// Стало — параметризованный запрос
$connection = \Bitrix\Main\Application::getConnection();
$result = $connection->query(
"SELECT * FROM my_custom_table WHERE ID = ?",
[$id]
);
// или через SqlHelper для сложных случаев
$helper = $connection->getSqlHelper();
$safeId = $helper->forSql((string)$id);
Глобальный $APPLICATION → Context и Application:
// Было
global $APPLICATION;
$APPLICATION->SetTitle('Моя страница');
$APPLICATION->IncludeFile('/local/include/header.php');
// Стало — в контексте компонента или контроллера
$this->arResult['PAGE_TITLE'] = 'Моя страница';
// Подключение через D7-механизмы или Inertia/React-подход
Стратегия рефакторинга: поэтапно
Переписать весь проект за один раз — плохая идея. Даже небольшой интернет-магазин содержит 50 000+ строк кода. Правильный подход — послойный рефакторинг с выделением приоритетов.
Этап 1. Аудит. Инвентаризация проблемных мест:
- SQL-запросы с конкатенацией строк (потенциальные SQL-инъекции)
- Глобальные переменные в логике (
global $DB,global $USER,global $APPLICATION) - Тяжёлые запросы через
CIBlockElement::GetListбез лимитов - Дублирующийся код одной логики в разных файлах
Этап 2. Создание сервисного слоя. Новые классы-сервисы на D7 API для каждой зоны ответственности. Старый код вызывает новые сервисы.
Этап 3. Постепенная замена. По модулям и функциональным блокам. Каждый блок после замены — регрессионное тестирование.
Этап 4. Удаление устаревшего кода. Только когда новый путь проверен в бою.
Инфоблоки: переход на D7-классы
С версии Битрикс 20.x доступны автогенерируемые классы для инфоблоков через Bitrix\Iblock\Elements:
// Включение в настройках инфоблока — флаг "API-код"
// Генерируется класс с namespace Bitrix\Iblock\Elements
$result = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
'select' => ['ID', 'NAME', 'IBLOCK_SECTION_ID'],
'filter' => ['=ACTIVE' => 'Y'],
]);
Это не полная замена CIBlockElement — для записи (add/update) часто по-прежнему используется старый API, так как D7-обёртки для записи инфоблоков не покрывают все сценарии.
Типичные ловушки при рефакторинге
Потеря событий. Если старый код вызывал CIBlockElement::Update(), на это событие были навешаны обработчики (OnAfterIBlockElementUpdate). При переходе на D7-методы события ORM другие. Нужна проверка: какие обработчики завязаны на старые события.
Различие в результатах GetList vs getList. CIBlockElement::GetList возвращает свойства инфоблока в специфичном формате с суффиксами _VALUE, _ENUM_ID. ORM-методы возвращают другую структуру. Код, который обрабатывает результат, нужно адаптировать.
Транзакции. Старый API не всегда оборачивал операции в транзакции. D7 даёт явные транзакции:
$connection = \Bitrix\Main\Application::getConnection();
$connection->startTransaction();
try {
// несколько операций
$connection->commitTransaction();
} catch (\Throwable $e) {
$connection->rollbackTransaction();
throw $e;
}
Что рефакторить в первую очередь
| Приоритет | Что | Почему |
|---|---|---|
| Критично | SQL с конкатенацией строк | Безопасность |
| Высокий | Тяжёлые GetList без лимитов | Производительность |
| Средний | Бизнес-логика в компонентах | Поддерживаемость |
| Плановый | Стилистические глобальные переменные | Читаемость |
Сроки
| Объём проекта | Срок рефакторинга |
|---|---|
| Небольшой сайт (до 30 файлов с логикой) | 2–4 недели |
| Средний интернет-магазин (50–150 файлов) | 2–3 месяца |
| Крупный портал или маркетплейс | 4–8 месяцев (поэтапно) |
Рефакторинг — это технический долг, который платишь сейчас, чтобы не платить в три раза больше через год. Код на старом API не становится надёжнее со временем — с каждым обновлением Битрикс риск несовместимости растёт.







