Розробка системи дистрибуції контенту на 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 тижнів залежно від числа сайтів і складності трансформацій.







