Создание компонента Битрикс - задача, с которой рано или поздно сталкивается каждый, кто разрабатывает на этой CMS дольше пары месяцев. Стандартные news.list, catalog.section и bitrix.include закрывают большую часть типовых блоков, но как только в макете появляется вывод из двух инфоблоков сразу, интеграция с внешним API или логика, завязанная на права пользователя, - начинается написание своего кода. Ниже - порядок действий, который использую на практике: с чего начинать структуру файлов, как не потерять кеш и на чём чаще всего спотыкаются те, кто делает первый компонент.
Когда писать свой компонент, а когда хватит стандартного
Первый вопрос, который задаю себе перед тем как открывать редактор, - а нужен ли вообще отдельный компонент, или задачу закрывает готовый с нужными параметрами. Битрикс поставляет несколько сотен компонентов, и половина самодельных решений, которые видел у клиентов, дублирует то, что уже есть в комплекте - просто автор не разобрался с параметрами существующего.
| Ситуация | Хватит стандартного | Нужен свой |
|---|---|---|
| Вывод списка новостей или товаров без нестандартной выборки | да | нет |
| Объединение данных из двух и более инфоблоков в один вывод | нет | да |
| Интеграция с внешним сервисом - СДЭК, эквайринг Т‑Банка, CRM | нет | да |
| Логика, зависящая от группы пользователя или сессии | частично | да |
| Один и тот же блок нужен на 5+ страницах с разными настройками | копипаст параметров плохо масштабируется | да, через параметры компонента |
Если по строке «нужен свой» набирается два пункта и больше - время открывать /local/components/. Когда таких задач становится много и разбираться с ядром компонента некогда, обычно проще отдать разработку кастомного компонента на Битриксе на сторону, чем тратить неделю на чтение исходников ядра ради одной интеграции.
Из чего состоит компонент - минимальный набор файлов
Компонент - это не один файл, а папка с обязательной структурой. Битрикс ищет её по пути /местоположение/пространство_имён/имя_компонента/ и ждёт внутри конкретный набор:
- .description.php - имя и описание компонента для визуального редактора, без него компонент не появится в списке при добавлении на страницу через админку;
- .parameters.php - массив параметров, которые видит редактор при настройке компонента;
- component.php - логика: выборка данных, обработка параметров, запись в $arResult;
- templates/.default/template.php - вывод HTML на основе $arResult, минимум один шаблон обязателен;
- templates/.default/style.css и script.js - по необходимости, шаблон сайта подключит их сам;
- lang/ru/component.php и языковой файл шаблона - если в коде есть текстовые константы.
Для публичных компонентов, которые попадут в несколько проектов, вместо component.php завожу class.php с классом-наследником CBitrixComponent - так удобнее переиспользовать методы и тестировать логику отдельно от вывода. Для разовой задачи под конкретный сайт хватает обычного component.php - усложнять без причины смысла нет.
Пошаговое создание компонента 1С-Битрикс
Параметры в .parameters.php
Начинаю всегда с параметров - они задают контракт компонента: какие данные принимает вход и что редактор сможет менять без правки кода.
$arComponentParameters = array(
'PARAMETERS' => array(
'IBLOCK_ID' => array(
'PARENT' => 'BASE',
'NAME' => 'ID инфоблока',
'TYPE' => 'STRING',
),
'CACHE_TIME' => array(
'PARENT' => 'CACHE_SETTINGS',
'NAME' => 'Время кеширования (сек.)',
'TYPE' => 'STRING',
'DEFAULT' => 3600,
),
),
);
PARENT со значением BASE или CACHE_SETTINGS - группы, по которым Битрикс раскладывает параметры на вкладках редактора. Свои группы можно добавить через блок GROUPS, если параметров больше десяти и они логически разные.
Логика в component.php
В component.php - весь код, который трогает базу или внешний API. Правило простое: шаблон не должен знать, откуда взялись данные, а component.php не должен знать, как они отрисуются. Нарушение этого правила - причина половины багов, когда через полгода меняешь шаблон и заодно ломаешь выборку, потому что логика и вывод были перемешаны в одном файле.
if ($this->StartResultCache()) {
$arResult['ITEMS'] = getItemsFromIblock($arParams['IBLOCK_ID']);
if (empty($arResult['ITEMS'])) {
$this->AbortResultCache();
} else {
$this->SetResultCacheKeys(array('ITEMS'));
}
$this->IncludeComponentTemplate();
}
StartResultCache проверяет кеш и сразу создаёт его, если раньше он не существовал - внутри условия пишется весь дорогой код: запросы к базе, обращения к внешнему API, тяжёлые вычисления.
Шаблон и вывод
template.php получает готовый $arResult и просто печатает HTML. Никаких SELECT и cURL внутри шаблона - если для вывода не хватает данных, значит их не докрутили в component.php, а не в шаблоне на скорую руку.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Кэширование - где компонент теряет скорость
Собственный кеш - главная причина, по которой самодельные компоненты либо жрут базу на каждый хит, либо показывают данные недельной давности. StartResultCache кеширует результат на диске или в memcached на время из CACHE_TIME, но если в выборке участвуют инфоблоки, нужна ещё подписка на управляемый кеш - иначе после смены цены товара в каталоге старое значение провисит в кеше до истечения TTL, а это может быть и сутки.
Для инфоблоков подписка выглядит так: SetResultCacheKeys плюс регистрация тега через модуль iblock - Битрикс сам сбросит кеш конкретного компонента при изменении элемента, к которому тег привязан. Без этого шага на интернет-магазине с частым обновлением остатков через обмен с 1С компонент будет отдавать неактуальные цифры, и разбираться с этим придётся не мне, а саппорту клиента через месяц после сдачи проекта.
Типичные ошибки при написании своего компонента
- Логика и вывод в одном файле - компонент невозможно ни кешировать частично, ни переиспользовать шаблон под другой дизайн;
- Отсутствие проверки входных параметров - $arParams[‘IBLOCK_ID’] без intval() или htmlspecialcharsbx() открывает дорогу к некорректным запросам, если параметр приходит из GET;
- Забытый $this->AbortResultCache() при пустой выборке - Битрикс закэширует пустой результат и будет отдавать его до истечения TTL, даже когда данные уже появились;
- Копирование чужого компонента без замены пространства имён в CLASS и в путях - на проекте с несколькими похожими компонентами это приводит к конфликту имён классов и белому экрану;
- Компонент без .description.php - для работы через include это не критично, но он не появится в визуальном редакторе, и вёрстальщик потом полдня ищет, почему блок не добавляется через админку.
Где размещать компонент и как его подключать
Свои компоненты кладу в /local/components/, а не в /bitrix/components/ - второй каталог перезатирается при обновлении ядра и модулей из маркетплейса, и терять код при апдейте не хочется никому. Подключение - через стандартный вызов:
$APPLICATION->IncludeComponent(
"vendor:component.name",
".default",
array(
"IBLOCK_ID" => 12,
"CACHE_TIME" => 3600,
)
);
Пространство имён vendor через двоеточие - не формальность, а защита от конфликтов, если на проекте когда-нибудь окажется модуль с похожим названием компонента от другого разработчика или из маркетплейса.
Перед сдачей компонента проверяю три вещи: работает ли он при пустой выборке и не падает ли белым экраном, сбрасывается ли кеш при изменении данных и не тянет ли лишние SQL-запросы - смотрю через встроенный монитор производительности в панели администратора, вкладку «SQL-запросы».
Разобраться перед стартом
Консультация
от 3 000 ₽
Подробнее →Частые вопросы
Сколько времени занимает написание простого компонента?
Вывод списка из одного инфоблока с базовой фильтрацией и своим шаблоном - обычно 2-4 часа вместе с версткой. Интеграция с внешним API вроде калькулятора СДЭК или эквайринга занимает уже день-два, потому что добавляется обработка сетевых ошибок и логирование.
Использовать старый API CIBlockElement или классы D7 (Bitrix\Main)?
На новых проектах беру D7 - ORM даёт готовую валидацию, события и более читаемые запросы через query builder. Старый API оставляю только когда компонент дорабатывает существующий код на CIBlockElement - переписывать рабочую часть ради стиля смысла не вижу.
Чем компонент отличается от модуля?
Компонент - это единица вывода с логикой и шаблоном, привязанная к конкретной странице или блоку. Модуль - набор классов, обработчиков событий и таблиц в базе, который может вообще не иметь визуального представления. Часто в одном модуле лежит десяток компонентов, которые пользуются его классами.
Обязательно ли делать .description.php и .parameters.php?
.description.php нужен, если компонент должен добавляться через визуальный редактор страницы - без него подключить получится только руками через include в коде шаблона. .parameters.php обязателен, если хотя бы один параметр планируется менять без правки PHP - для совсем служебного компонента, который вызывается один раз с фиксированными аргументами, можно обойтись без него, но это скорее исключение, чем практика.