Рефакторинг старого 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 не стає надійнішим з часом — з кожним оновленням Бітрікс ризик несумісності зростає.







