Избавляемся от ID инфоблока при работе с разделами
Проблема
В типичном проекте на 1С-Битрикс код работы с разделами напрямую взаимодействует с ID инфоблока. При каждом запросе к SectionTable или CIBlockSection приходится явно указывать фильтр по инфоблоку. Если нужно изменить ID инфоблока или перенести код на другой проект — начинается ад с поиском и заменой всех вхождений.
Решение
Класс Bitrix\Iblock\Model\Section предоставляет метод compileEntityByIblock(), который создаёт специализированный класс для работы с разделами конкретного инфоблока. Все запросы через этот класс автоматически фильтруются по нужному IBLOCK_ID без явного указания.
Было: магические числа везде
use Bitrix\Iblock\SectionTable;
// Приходится каждый раз указывать IBLOCK_ID
$sections = SectionTable::getList([
'select' => ['ID', 'NAME', 'CODE'],
'filter' => [
'IBLOCK_ID' => 10, // Что это за инфоблок?
'ACTIVE' => 'Y'
]
])->fetchAll();
// И снова тот же ID в другом месте
$section = SectionTable::getByPrimary(25, [
'filter' => ['IBLOCK_ID' => 10] // Дублирование!
])->fetch();
Стало: чистый код без дублирования
use Bitrix\Iblock\Model\Section;
// Один раз создаём класс для инфоблока по API_CODE
$catalogSectionEntity = Section::compileEntityByIblock('catalog');
// IBLOCK_ID больше не нужен - всё фильтруется автоматически
$sections = $catalogSectionEntity::getList([
'select' => ['ID', 'NAME', 'CODE'],
'filter' => ['ACTIVE' => 'Y']
])->fetchAll();
Бонус: автоматическая связь с родителем
Помимо избавления от IBLOCK_ID, получаем ещё и связь PARENT_SECTION для работы с иерархией:
$catalogSectionEntity = Section::compileEntityByIblock('catalog');
// Получаем раздел с данными родителя одним запросом
$section = $catalogSectionEntity::getList([
'filter' => ['=CODE' => 'laptops'],
'select' => ['ID', 'NAME', 'PARENT_SECTION.NAME']
])->fetchObject();
echo $section->getName(); // "Ноутбуки"
echo $section->getParentSection()?->getName(); // "Компьютеры"
Практический пример: хлебные крошки без IBLOCK_ID
use Bitrix\Iblock\Model\Section;
// Инициализируем класс для каталога
$catalogSectionEntity = Section::compileEntityByIblock('catalog');
$section = $catalogSectionEntity::query()
->setSelect([
'ID',
'NAME',
'CODE',
'PARENT_SECTION.NAME',
'PARENT_SECTION.PARENT_SECTION.NAME'
])
->where('CODE', 'gaming-laptops')
->exec()
->fetchObject();
// Строим хлебные крошки рекурсивно
$breadcrumbs = [];
$current = $section;
while ($current) {
$breadcrumbs[] = [
'name' => $current->getName(),
'code' => $current->getCode()
];
$current = $current->getParentSection();
}
$breadcrumbs = array_reverse($breadcrumbs);
Что получаем
- Нет магических чисел:
IBLOCK_IDуказан один раз при создании класса - Переносимость: изменили ID инфоблока — код работает без изменений
- Читаемость: не нужно помнить, что
10— это каталог, а15— новости - Меньше ошибок: невозможно забыть добавить фильтр по
IBLOCK_ID - Связь с родителем: автоматическая
PARENT_SECTIONдля иерархии