Компонент Битрикс: типичные ошибки и как их избежать
Самописный компонент Битрикс быстро превращается в источник 500-х, пустого кеша и медленных запросов, если смешать SQL, шаблон и бизнес-логику. Разбираем структуру компонента, кеширование, параметры и ошибки, которые дорого исправлять в проде.

Самописный компонент Битрикс обычно ломается не из-за сложной логики, а из-за границ ответственности: запросы оказываются в шаблоне, параметры не проверяются, кеш сохраняет чужие данные, а код работает только из административного раздела. В этой практике разберём компонент списка элементов инфоблока для 1C-Битрикс: Управление сайтом 24.x–25.x и PHP 8.1+, покажем безопасную структуру и разберём ошибки, которые чаще всего находят уже после релиза.
Сначала определите границы компонента
Компонент должен принять параметры, получить данные, подготовить arResult и передать управление шаблону. Шаблон отвечает только за HTML. Подключение модулей, запросы к инфоблоку и проверка условий доступа в нём не нужны.
Для примера возьмём компонент acme:catalog.list в каталоге /local/components/acme/catalog.list/:
.description.php— название и описание компонента;.parameters.php— параметры, которые видит редактор в визуальном редакторе;component.php— получение данных и кеширование;template.php— разметка результата;lang/— языковые файлы, если компонент должен работать в нескольких языках.
Не кладите компонент в /bitrix/components. Обновление ядра или перенос сайта может затереть эти файлы. Каталог /local/components предназначен для собственного кода.
Хороший компонент можно заменить другим шаблоном без переписывания запроса. Если для изменения цвета кнопки приходится открывать
component.php, граница уже проведена неправильно.
Ошибка 1. Запросы и бизнес-логика попадают в шаблон
Рабочий шаблон должен получать готовый массив. Вызов CIBlockElement::GetList внутри template.php создаёт сразу несколько проблем: шаблон нельзя нормально переиспользовать, ошибки базы смешиваются с HTML, а кеширование становится непредсказуемым.
В component.php запрос выглядит так:
<?php
use Bitrix\Main\Loader;
if (!Loader::includeModule('iblock')) {
ShowError('Модуль инфоблоков не подключён');
return;
}
$iblockId = (int)$arParams['IBLOCK_ID'];
$itemLimit = max(1, min(100, (int)$arParams['COUNT']));
if ($this->startResultCache(false, [$iblockId, $itemLimit])) {
$items = [];
$result = CIBlockElement::GetList(
['SORT' => 'ASC', 'ID' => 'DESC'],
[
'IBLOCK_ID' => $iblockId,
'ACTIVE' => 'Y',
'CHECK_PERMISSIONS' => 'Y',
],
false,
['nTopCount' => $itemLimit],
['ID', 'NAME', 'DETAIL_PAGE_URL']
);
while ($item = $result->GetNext()) {
$items[] = [
'ID' => (int)$item['ID'],
'NAME' => $item['NAME'],
'URL' => $item['DETAIL_PAGE_URL'],
];
}
$arResult['ITEMS'] = $items;
$this->includeComponentTemplate();
}
Проверка результата: в шаблоне доступны только подготовленные значения, а запрос выполняется один раз на построение кеша. Для D7-решений можно использовать ORM, но не смешивайте его с запросами в шаблоне.
Ошибка 2. Параметры принимаются без ограничений
Значения из настроек компонента тоже нужно нормализовать. Параметр количества элементов не должен превращаться в отрицательное число, а идентификатор инфоблока — в произвольную строку.
<?php
$arComponentParameters = [
'PARAMETERS' => [
'IBLOCK_ID' => [
'PARENT' => 'BASE',
'NAME' => 'ID инфоблока',
'TYPE' => 'STRING',
'DEFAULT' => '0',
],
'COUNT' => [
'PARENT' => 'BASE',
'NAME' => 'Количество элементов',
'TYPE' => 'STRING',
'DEFAULT' => '10',
],
'CACHE_TIME' => [
'DEFAULT' => 3600,
],
],
];
В компоненте приводите типы ещё раз. Настройки, введённые через админку, не стоит считать доверенными только потому, что их заполняет сотрудник компании.
Ошибка 3. Кеш не учитывает параметры и права
Кеш компонента — сохранённый результат его работы, который Битрикс отдаёт вместо повторного выполнения запроса. Если компонент кешируется без ID инфоблока и лимита, страницы с разными настройками могут получить один и тот же результат.
В массив ключа кеша включайте параметры, которые меняют ответ: ID инфоблока, сортировку, фильтр, число элементов и признаки, зависящие от пользователя. Не включайте туда случайные значения, иначе кеш перестанет переиспользоваться.
Отдельный риск — персональные данные. Компонент с кешем по умолчанию может отдать одному посетителю результат, сформированный для другого. Для персонального вывода отключайте кеширование или учитывайте нужный контекст пользователя в ключе. Проверка прав на элементы должна оставаться включённой, если компонент показывает закрытый контент.
Ошибка 4. Шаблон выводит данные без экранирования
Даже если название элемента пришло из админки, его нельзя бездумно вставлять в HTML. Редактор мог сохранить кавычки, HTML или другой пользовательский ввод.
<?php if (!empty($arResult['ITEMS'])): ?>
<ul class="catalog-list">
<?php foreach ($arResult['ITEMS'] as $item): ?>
<li>
<a href="<?= htmlspecialcharsbx($item['URL']) ?>">
<?= htmlspecialcharsbx($item['NAME']) ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>Элементы не найдены.</p>
<?php endif; ?>
htmlspecialcharsbx — функция экранирования, используемая в окружении Битрикс. Для URL этого недостаточно, если вы самостоятельно принимаете внешние адреса: дополнительно разрешайте только ожидаемые схемы и форматы ссылок.
Ошибка 5. Всё помещают в component.php
Большой файл быстро становится неуправляемым. Обычно часть подготовки можно вынести в result_modifier.php: например, сгруппировать уже полученные элементы или добавить вычисляемое поле. Этот файл не должен выполнять второй тяжёлый запрос без явной причины.
| Файл или механизм | Что в нём делать | Что туда не переносить |
|---|---|---|
component.php | Параметры, модуль, запрос, кеш, arResult | Разметку и стили |
result_modifier.php | Лёгкую подготовку результата перед шаблоном | Повторный запрос к базе на каждый элемент |
template.php | HTML и безопасный вывод | Запросы и изменение настроек компонента |
component_epilog.php | Действия после подключения шаблона, если они нужны | Формирование основного списка |
Если код нужен только одному шаблону, не превращайте его в универсальный слой. Но если в проекте появляются второй шаблон, сортировка или фильтр, вынесите повторяющуюся логику в компонент, а не копируйте её в каждую тему.
Что ломается на практике
- Класс или функция не найдены. Обычно забыли подключить модуль через
Loader::includeModuleили вызвали API модуля, которого нет на окружении. - Список пустой, хотя элементы есть. Проверьте ID инфоблока, активность элементов, права текущего пользователя и фильтр
CHECK_PERMISSIONS. - После изменения элемента сайт показывает старые данные. Проверьте настройки кеша компонента и очистите кеш после изменения логики. Для массового обновления продумайте событие или административную процедуру очистки.
- Вёрстка ломается на кавычках и специальных символах. Проверьте, что значения экранируются в HTML-контексте, а не только при записи в базу.
- Страница стала медленной после добавления поля. Посмотрите фактический SQL и количество запросов. Не запрашивайте свойства и изображения для каждого элемента отдельным циклом без замера.
Как проверить компонент до релиза
- Откройте страницу с пустым инфоблоком. Должно появиться понятное состояние без ошибок PHP.
- Проверьте неверный ID инфоблока и нулевой лимит. Компонент не должен выполнять неконтролируемый запрос или выводить предупреждения.
- Откройте страницу под пользователем без доступа к закрытым элементам. Закрытые данные не должны попасть в результат.
- Измените название элемента и проверьте страницу после очистки кеша. Новое значение должно появиться без ручного редактирования шаблона.
- Подключите второй шаблон компонента. Если для этого пришлось копировать запрос или менять
component.php, разделение ответственности нарушено.
Для диагностики используйте режим отладки и встроенные инструменты профилирования Битрикс в тестовом окружении. Сравнивайте число запросов и время генерации страницы до и после изменения. Универсальных цифр для «быстрого компонента» нет: результат зависит от объёма инфоблока, индексов, кеша и конфигурации PHP.
Когда компоненту нужен другой подход
Если компонент отдаёт только статический список, стандартного кеширования результата достаточно. Если ответ зависит от пользователя, не копируйте шаблон ради отключения кеша: явно опишите зависимость и проверьте, не попадают ли персональные данные в общий кеш.
Если компонент обслуживает AJAX-запросы, отделите получение данных от HTML и проверьте CSRF-защиту, права и ограничение частоты запросов. AJAX не отменяет требования к экранированию и проверке параметров.
Если выборка выросла до тысяч элементов, сначала измерьте запрос и план выполнения, а уже потом переходите на ORM, постраничную навигацию или отдельный сервис. Инвалидация кеша — отдельная тема; здесь важнее не забыть, что старый результат имеет срок жизни.
Что сделать дальше
Создайте тестовую страницу с компонентом и зафиксируйте четыре показателя: время генерации, количество SQL-запросов, размер результата и поведение при включённом кеше. Затем проверьте три сценария — гость, авторизованный пользователь и пользователь без доступа к части элементов. После этого можно добавлять сортировку, фильтр и второй шаблон: каждая новая возможность должна появляться как параметр или подготовленное поле, а не как ещё один запрос в HTML.
IT-архитектор / SQL-оптимизатор: Поиск N+1, оптимизация запросов, code review, поиск багов.
Спросить за 20 ₽Источники: Официальная документация 1C-Битрикс: компоненты, Официальная документация 1C-Битрикс: API D7
Частые вопросы
Можно ли писать компонент в /bitrix/components?
Почему компонент показывает старые данные после изменения элемента?
Нужно ли отключать кеш для компонентов с правами доступа?
Что делать, если у меня другая версия Битрикс или PHP?
Почему список пустой, хотя в инфоблоке есть элементы?
Нужно ли очищать кеш после каждого изменения кода?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.