Перейти к содержимому

Код для двух сайтов - текущий сайт, настройки, общие данные

Пишем код, который одинаково работает на обоих сайтах одной копии: с правильным сайтом, своими настройками и без смешанного кэша.

Решение

Определяем текущий сайт:

$siteId = \Bitrix\Main\Context::getCurrent()->getSite(); // в публичной части
$site = \Bitrix\Main\SiteTable::getList([
'select' => ['LID', 'NAME', 'SERVER_NAME', 'DIR'],
'filter' => ['=ACTIVE' => 'Y'],
])->fetchAll();
// в консоли и в агенте текущего сайта нет: его задают явно

Текущий сайт берут из окружения, а не из константы в коде. Жёстко записанный идентификатор работает ровно до появления второго сайта и ломается молча, без единой ошибки.

Разводим настройки по сайтам:

Option::set('vendor.shop', 'manager_email', 'shop@example.org', 's1');
$email = Option::get('vendor.shop', 'manager_email', '', $siteId);
// последний аргумент - сайт: без него значение общее для всех сайтов

Настройка модуля умеет храниться отдельно для сайта. Адрес получателя писем, номер склада и режим обмена почти всегда разные у двух сайтов, и хранить их общими - готовая путаница.

Разводим кэш по сайтам:

$cache->initCache(3600, 'menu_' . $siteId . '_' . $sectionId, '/vendor/menu');
// без сайта в ключе второй сайт получит меню первого
// то же самое касается своих таблиц: поле сайта в них обязательно

Ключ кэша включает сайт, иначе данные смешаются. Ошибка проявляется не сразу: до первого сброса кэша всё выглядит правильно, а потом на витрине второго сайта появляется чужое меню.

Задаём сайт в фоновом задании:

$siteId = 's1'; // определяем сами
$site = \Bitrix\Main\SiteTable::getById($siteId)->fetch();
$url = 'https://' . $site['SERVER_NAME'] . $itemUrl; // ссылки собираем явно
\Bitrix\Main\Mail\Event::send(['EVENT_NAME' => 'VENDOR_REPORT', 'LID' => $siteId, ...]);

В задании по расписанию текущего сайта нет вовсе. Почтовое событие, кэш и ссылки там нужно задавать руками, иначе письмо уйдёт с шаблоном первого сайта и со ссылками на его домен.

Абсолютные ссылки собирают из адреса сайта, а не из адреса запроса. В фоновом задании адреса запроса нет, а в публичной части он приводит к ссылкам на тот домен, с которого зашли.

Общий каталог на два сайта - решение по смыслу, а не по устройству. Инфоблок привязывают к сайтам явно, и от этой привязки зависит и выдача, и ссылки, и права.

Проверять правки нужно на обоих сайтах, а не на том, с которого удобнее. Половина ошибок многосайтовости видна только на втором сайте, куда никто не заходит.

Типичные проблемы

Письма второго сайта приходят с чужим шаблоном.

Почтовое событие отправлено вообще без всякого указания того самого нужного сайта. В фоновом задании сайт задают явным аргументом при каждом таком его вызове.

На витрине второго сайта чужое меню.

Ключ кэша не включает в себя идентификатор этого самого конкретного сайта копии. Ошибка проявляется только после первого сброса всего этого самого кэша страниц.

Ссылки в письме ведут на другой домен.

Адрес собран из текущего запроса, а не из настроек сайта. В задании по расписанию запроса нет вовсе.

Скрипт из консоли работает не с тем сайтом.

В консоли текущего сайта не существует, и код берёт первый попавшийся. Сайт передают такому скрипту отдельным параметром при самом его первом запуске.

Настройка поменялась сразу на двух сайтах.

Значение сохранено без указания сайта и стало общим. Такие настройки хранят отдельно для каждого сайта.

Частые вопросы

Как получить сайт в консольном скрипте?

Передать его параметром запуска: текущего сайта там нет. Брать первый активный - источник трудных ошибок.

Можно ли держать общий каталог на два сайта?

Да, инфоблок привязывается к нескольким сайтам. Цены и наличие при этом обычно всё равно разводят.

Как хранить настройку для одного сайта?

Указывать сайт при сохранении и при чтении. Без него значение становится общим.

Чем второй сайт отличается от поддомена?

Сайт - это отдельный набор настроек, шаблонов и данных. Поддомен без этого остаётся тем же сайтом.

Смежное

Первоисточник