В 1С-Битрикс навигационная цепочка (хлебные крошки) формируется двумя способами:
- автоматически — компонентами
bitrix:catalog,bitrix:news,bitrix:catalog.section,bitrix:catalog.elementчерез параметры ADD_SECTIONS_CHAIN и ADD_ELEMENT_CHAIN; - вручную — через метод
$APPLICATION->AddChainItem().
Чтобы на страницах разделов каталога и детальных карточек товаров были разные цепочки, нужно перехватить управление навигационной цепочкой. Рассмотрим два подхода.
Способ 1. Настройка параметров компонента каталога (базовый)
Типовой комплексный компонент bitrix:catalog имеет в настройках страниц section.php и element.php ключевые параметры:
- ADD_SECTIONS_CHAIN — добавляет разделы в цепочку;
- SET_TITLE — устанавливает заголовок страницы;
- SET_LAST_MODIFIED — устанавливает дату модификации.
Для раздела (section.php) компонент catalog.section использует параметр ADD_SECTIONS_CHAIN, который строит цепочку от корня до текущего раздела.
Для детальной карточки (element.php) компонент catalog.element также использует ADD_SECTIONS_CHAIN, но дополнительно может добавлять сам элемент через $APPLICATION->AddChainItem() внутри своего выполнения.
Ограничение: настройки одни для всех типов страниц — вы не сможете через параметры сделать принципиально разные пути.
Способ 2. Собственный компонент breadcrumb с условиями (рекомендуемый)
Создайте свой компонент или доработайте шаблон bitrix:breadcrumb, который анализирует, на каком типе страницы мы находимся, и формирует нужную цепочку.
Базовая логика в файле class.php компонента:
<?php
use Bitrix\Main\Loader;
use Bitrix\Iblock\SectionTable;
use Bitrix\Iblock\ElementTable;
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
class CustomBreadcrumb extends \CBitrixComponent
{
public function executeComponent()
{
global $APPLICATION;
// Очищаем стандартную цепочку, если нужно строить свою
// $APPLICATION->SetTitle(''); // опционально
$this->arResult = [];
// Определяем тип страницы
$isSection = isset($_REQUEST['SECTION_ID']) || (SITE_TEMPLATE_ID && defined('SECTION_ID'));
$isElement = isset($_REQUEST['ELEMENT_ID']) || (SITE_TEMPLATE_ID && defined('ELEMENT_ID'));
// Или определяем по URL
$requestUri = $_SERVER['REQUEST_URI'];
if (preg_match('#/catalog/(.+?)/$#', $requestUri, $m)) {
// Страница раздела каталога
$sectionCode = $m[1];
$this->buildSectionChain($sectionCode);
} elseif (preg_match('#/catalog/(.+?)/(.+?)/$#', $requestUri, $m)) {
// Детальная страница товара
$sectionCode = $m[1];
$elementCode = $m[2];
$this->buildDetailChain($sectionCode, $elementCode);
} else {
// Другие страницы — стандартное поведение
$this->arResult = $APPLICATION->GetNavChain();
}
$this->includeComponentTemplate();
}
protected function buildSectionChain($sectionCode)
{
// Для раздела — короткий путь
// Главная / Каталог / [Название раздела]
global $APPLICATION;
$APPLICATION->AddChainItem('Главная', '/');
$APPLICATION->AddChainItem('Каталог', '/catalog/');
$APPLICATION->AddChainItem('Товары в разделе ' . $sectionCode);
$this->arResult = $APPLICATION->GetNavChain();
}
protected function buildDetailChain($sectionCode, $elementCode)
{
// Для детальной карточки — другой путь
// Главная / Каталог / [Название раздела] / [Название товара]
global $APPLICATION;
$APPLICATION->AddChainItem('Главная', '/');
$APPLICATION->AddChainItem('Каталог', '/catalog/');
// Получаем название раздела
$sectionName = $this->getSectionName($sectionCode);
$APPLICATION->AddChainItem($sectionName, '/catalog/' . $sectionCode . '/');
// Получаем название элемента
$elementName = $this->getElementName($elementCode);
$APPLICATION->AddChainItem($elementName);
$this->arResult = $APPLICATION->GetNavChain();
}
protected function getSectionName($code)
{
if (!Loader::includeModule('iblock')) {
return $code;
}
$section = SectionTable::getList([
'filter' => ['=CODE' => $code],
'select' => ['NAME'],
'limit' => 1
])->fetch();
return $section ? $section['NAME'] : $code;
}
protected function getElementName($code)
{
if (!Loader::includeModule('iblock')) {
return $code;
}
$element = ElementTable::getList([
'filter' => ['=CODE' => $code],
'select' => ['NAME'],
'limit' => 1
])->fetch();
return $element ? $element['NAME'] : $code;
}
}
Шаблон компонента (templates/.default/template.php):
<?php if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die(); ?>
<div class="breadcrumbs">
<?php foreach ($arResult as $key => $item): ?>
<?php if ($key > 0): ?>
<span class="breadcrumbs__separator">/</span>
<?php endif; ?>
<?php if (!empty($item['LINK'])): ?>
<a href="<?= htmlspecialcharsbx($item['LINK']) ?>" class="breadcrumbs__link">
<?= htmlspecialcharsbx($item['TITLE']) ?>
</a>
<?php else: ?>
<span class="breadcrumbs__current">
<?= htmlspecialcharsbx($item['TITLE']) ?>
</span>
<?php endif; ?>
<?php endforeach; ?>
</div>
Способ 3. Перехват в шаблоне сайта (быстрый)
Можно не создавать отдельный компонент, а в файле header.php шаблона сайта, перед вызовом bitrix:breadcrumb, очистить цепочку и построить свою:
<?php
global $APPLICATION;
// Проверяем, находимся ли мы на детальной странице каталога
if (defined('ERROR_404') && ERROR_404 === 'Y') {
// Ничего не делаем
} elseif (strpos($_SERVER['REQUEST_URI'], '/catalog/') !== false) {
// Очищаем стандартную цепочку
$APPLICATION->SetNavChain([]);
// Определяем тип страницы
if (preg_match('#/catalog/([^/]+)/([^/]+)/$#', $_SERVER['REQUEST_URI'])) {
// Детальная — добавляем раздел и товар
$APPLICATION->AddChainItem('Главная', '/');
$APPLICATION->AddChainItem('Каталог', '/catalog/');
$APPLICATION->AddChainItem('Все товары раздела', '/catalog/' . $sectionCode . '/');
$APPLICATION->AddChainItem($elementName);
} elseif (preg_match('#/catalog/([^/]+)/$#', $_SERVER['REQUEST_URI'])) {
// Раздел — короткий путь
$APPLICATION->AddChainItem('Главная', '/');
$APPLICATION->AddChainItem('Каталог');
}
}
?>
<?php $APPLICATION->IncludeComponent('bitrix:breadcrumb', '', [
'START_FROM' => '0',
'PATH' => '',
'SITE_ID' => SITE_ID,
]); ?>
Способ 4. Использование события OnBeforeNavChain (продвинутый)
Через событие OnBeforeNavChain можно перехватить формирование цепочки до того, как она будет отдана компоненту breadcrumb:
// регистрируем в init.php
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'main',
'OnBeforeNavChain',
function (&$arChain) {
global $APPLICATION;
if (strpos($_SERVER['REQUEST_URI'], '/catalog/') !== false) {
// Полностью заменяем цепочку
$arChain = [];
$APPLICATION->AddChainItem('Главная', '/');
if (/* это детальная страница */) {
$APPLICATION->AddChainItem('Каталог', '/catalog/');
$APPLICATION->AddChainItem('Раздел', '/catalog/razdel/');
$APPLICATION->AddChainItem('Товар');
} else {
$APPLICATION->AddChainItem('Список товаров');
}
// Забираем обновлённую цепочку
$arChain = $APPLICATION->GetNavChain();
}
}
);
Рекомендации
- В параметрах комплексного компонента
bitrix:catalogна страницахsection.phpиelement.phpотключите ADD_SECTIONS_CHAIN и SET_TITLE, чтобы стандартный механизм не создавал цепочку автоматически. - Используйте Способ 2 (собственный компонент) — он наиболее гибкий, переиспользуемый и не конфликтует с обновлениями.
- При необходимости получайте данные через D7 ORM (
\Bitrix\Iblock\SectionTable,\Bitrix\Iblock\ElementTable) для лучшей производительности. - Для сложных сценариев (разные цепочки для разных типов каталогов, уровней вложенности и т.д.) комбинируйте определение через
$_SERVER['REQUEST_URI'], глобальные переменные и URL-шаблоны.