Разработка системы дистрибуции контента на 1С-Битрикс
Управлять контентом на одном сайте — просто. Проблема начинается, когда сайтов несколько: сеть региональных порталов, группа тематических ресурсов, мультиязычный проект или маркетплейс с витринами для разных каналов. Тиражировать изменения вручную — трудоёмко и ненадёжно. Система дистрибуции контента автоматизирует распространение материалов между источником и потребителями с гибким управлением: что, куда, когда и с какими трансформациями.
Архитектура: мастер и дочерние сайты
Типовая схема — один мастер-сайт (источник контента) и несколько дочерних (потребители). На Битриксе это решается несколькими способами в зависимости от инфраструктуры:
Многосайтовость Битрикса — если все сайты на одной установке. Элементы инфоблоков привязаны к сайтам через b_iblock_site. Один элемент может быть активен на нескольких сайтах одновременно. Управление через поле IBLOCK_ELEMENT.ACTIVE и связь с сайтами.
Распределённая схема — разные установки Битрикса. Нужен API-слой: мастер публикует контент через REST API или очередь сообщений, дочерние сайты подписываются и получают обновления.
Гибридная — CDN для медиафайлов, API для структурированного контента, прямая репликация БД для срочных обновлений.
Инфоблок-дистрибутор: таблицы и логика
Для отслеживания, что и куда распространено, нужна кастомная таблица:
CREATE TABLE content_distribution (
ID INT AUTO_INCREMENT PRIMARY KEY,
SOURCE_ELEMENT_ID INT NOT NULL, -- ID элемента на мастере
SOURCE_IBLOCK_ID INT NOT NULL,
TARGET_SITE_ID VARCHAR(8) NOT NULL, -- ID сайта-получателя
TARGET_ELEMENT_ID INT, -- ID на дочернем сайте (NULL до публикации)
STATUS ENUM('pending','published','failed','excluded') DEFAULT 'pending',
PUBLISHED_AT DATETIME,
ERROR TEXT,
INDEX (SOURCE_ELEMENT_ID),
INDEX (TARGET_SITE_ID, STATUS)
);
При публикации элемента на мастере — событие OnAfterIBlockElementAdd/Update запускает дистрибуцию. Обработчик проверяет правила: какие дочерние сайты должны получить этот тип контента, записывает задачи в таблицу.
Правила дистрибуции
Гибкая система правил определяет, какой контент куда идёт:
// Конфигурация правил дистрибуции
$distributionRules = [
[
'source_iblock_id' => 5, // Инфоблок «Новости»
'target_sites' => ['s2', 's3', 's4'], // Все региональные сайты
'filter' => [ // Только определённые категории
'PROPERTY_CATEGORY' => [1, 2], // IDs разделов «Федеральные новости»
],
'transform' => 'NewsTransformer', // Класс трансформации
'delay' => 0, // Немедленно
],
[
'source_iblock_id' => 8, // «Акции»
'target_sites' => ['s2'], // Только для одного региона
'filter' => ['PROPERTY_REGION' => 'msk'],
'transform' => null, // Без трансформации
'delay' => 3600, // Через час после публикации на мастере
],
];
Трансформация контента при дистрибуции
Контент редко распространяется «как есть». Типичные трансформации:
Адаптация ссылок — абсолютные ссылки внутри текста нужно заменить на ссылки дочернего сайта:
$content = preg_replace(
'|https://master-site\.ru/([^"\']+)|',
'https://regional-site.ru/$1',
$sourceContent
);
Перевод — для мультиязычных проектов. Интеграция с Google Translate API или DeepL для автоматического перевода, с последующей ручной корректурой:
$translated = $translationService->translate(
$element['DETAIL_TEXT'],
from: 'ru',
to: $targetSite['LANGUAGE']
);
Региональная адаптация — замена контактных данных, телефонов, адресов на региональные. Реализуется через шаблоны с плейсхолдерами {{PHONE}}, {{ADDRESS}}, которые подставляются при дистрибуции.
Подмена изображений — для разных каналов могут требоваться разные форматы или размеры. Сервис дистрибуции ресайзит при отдаче или хранит версии.
Обработка конфликтов редактирования
Если на дочернем сайте разрешена ручная правка — нужна логика слияния при обновлении с мастера:
- Политика «всегда перезаписать» — проще всего, но теряет локальные правки
-
Политика «не трогать вручную правленный» — флаг
LOCALLY_MODIFIEDна элементе, мастер не обновляет такие - Политика «слияние по полям» — некоторые поля всегда синхронизируются (заголовок, основной текст), другие могут быть локальными (мета-теги, региональные данные)
Реализация флага через пользовательское поле элемента инфоблока:
// При ручном сохранении на дочернем сайте
CIBlockElement::SetPropertyValues($elementId, IBLOCK_ID, 'Y', 'LOCALLY_MODIFIED');
// При дистрибуции с мастера
$locallyModified = CIBlockElement::GetProperty(IBLOCK_ID, $elementId, [], ['CODE' => 'LOCALLY_MODIFIED'])->Fetch();
if ($locallyModified['VALUE'] === 'Y' && $rule['respect_local_edits']) {
// Пропускаем обновление
continue;
}
Очередь и асинхронная обработка
При большом количестве сайтов или элементов синхронная дистрибуция в обработчике события — плохая идея: пользователь будет ждать сохранения несколько секунд.
Правильный подход: обработчик события только создаёт задачи в очереди, фактическая дистрибуция выполняется воркером асинхронно.
// Обработчик события (быстрый)
public static function onAfterElementUpdate(array $fields): void
{
if ($fields['IBLOCK_ID'] === MASTER_IBLOCK_ID) {
DistributionQueue::add($fields['ID'], $fields['IBLOCK_ID']);
}
}
// Воркер (Cron каждую минуту)
// php /var/www/bitrix/local/console/distribute_content.php
$pending = DistributionQueue::getPending(limit: 50);
foreach ($pending as $task) {
$distributor->distribute($task);
}
Мониторинг дистрибуции
| Метрика | Как отслеживать |
|---|---|
| Лаг дистрибуции | Разница между CREATED_AT и PUBLISHED_AT в таблице |
| Неудачные дистрибуции | STATUS='failed' за последний час |
| Расхождение количества | Сравнение count на мастере vs дочерних |
| Очередь | Размер STATUS='pending' больше N минут |
Этапы разработки
| Этап | Содержание | Срок |
|---|---|---|
| Проектирование | Схема дистрибуции, правила, политики | 3–5 дней |
| Ядро системы | Очередь, воркер, таблица статусов | 1 неделя |
| Коннекторы к дочерним сайтам | API-клиент или прямой доступ к БД | 1 неделя |
| Трансформации | Адаптация ссылок, перевод, регионализация | 1–2 недели |
| Административный интерфейс | Мониторинг, ручной запуск, логи | 1 неделя |
| Тестирование | Интеграционные тесты, тест конфликтов | 1 неделя |
Суммарно: 6–10 недель в зависимости от числа сайтов и сложности трансформаций.







