Навигация между элементами инфоблока — важный элемент UX, который позволяет пользователям легко перемещаться между связанными материалами. В этой статье я расскажу о нескольких способах реализации такой навигации в CMS 1С-Битрикс.
Способ 1: Базовая реализация через CIBlockElement::GetList
Самый простой способ добавить навигацию — модифицировать шаблон компонента news.detail:
<?
// В файле template.php вашего шаблона
$arFilter = array(
"IBLOCK_ID" => $arResult["IBLOCK_ID"],
"ACTIVE" => "Y",
"CHECK_PERMISSIONS" => "Y"
);
$arSelect = array("ID", "NAME", "DETAIL_PAGE_URL");
// Получаем предыдущий элемент
$resPrev = CIBlockElement::GetList(
array("SORT" => "ASC", "ID" => "DESC"),
$arFilter,
false,
array("nElementID" => $arResult["ID"], "nPageSize" => 1),
$arSelect
);
$arPrev = $resPrev->GetNext();
// Получаем следующий элемент
$resNext = CIBlockElement::GetList(
array("SORT" => "DESC", "ID" => "ASC"),
$arFilter,
false,
array("nElementID" => $arResult["ID"], "nPageSize" => 1),
$arSelect
);
$arNext = $resNext->GetNext();
?>
<?if($arPrev || $arNext):?>
<div class="news-navigation">
<?if($arPrev):?>
<a href="<?=$arPrev["DETAIL_PAGE_URL"]?>" class="news-navigation-prev">
← <?=$arPrev["NAME"]?>
</a>
<?endif;?>
<?if($arNext):?>
<a href="<?=$arNext["DETAIL_PAGE_URL"]?>" class="news-navigation-next">
<?=$arNext["NAME"]?> →
</a>
<?endif;?>
</div>
<?endif;?>Способ 2: Улучшенная версия с учетом разделов
Для более точной навигации, особенно в сложных структурах, следует учитывать разделы:
<?
$arFilter = array(
"IBLOCK_ID" => $arResult["IBLOCK_ID"],
"ACTIVE" => "Y",
"ACTIVE_DATE" => "Y"
);
// Учитываем текущий раздел
if ($arResult["IBLOCK_SECTION_ID"]) {
$arFilter["SECTION_ID"] = $arResult["IBLOCK_SECTION_ID"];
$arFilter["INCLUDE_SUBSECTIONS"] = "Y";
}
// Используем кэширование
$cache = new CPHPCache();
$cacheTime = 3600;
$cacheID = 'news_nav_'.$arResult["ID"];
$cachePath = '/news_navigation/';
if ($cache->InitCache($cacheTime, $cacheID, $cachePath)) {
$arNav = $cache->GetVars();
} elseif ($cache->StartDataCache()) {
$res = CIBlockElement::GetList(
array(
$arParams["SORT_BY1"] => $arParams["SORT_ORDER1"],
$arParams["SORT_BY2"] => $arParams["SORT_ORDER2"],
"ID" => "ASC"
),
$arFilter,
false,
array("nElementID" => $arResult["ID"], "nPageSize" => 1),
array("ID", "NAME", "DETAIL_PAGE_URL", "PREVIEW_PICTURE")
);
$arNav = array();
while ($item = $res->GetNext()) {
$arNav[] = $item;
}
$cache->EndDataCache($arNav);
}
// Определяем соседние элементы
if (count($arNav) > 2) {
$arResult["PREV"] = $arNav[2]; // Предыдущий
$arResult["NEXT"] = $arNav[0]; // Следующий
} elseif (count($arNav) == 2) {
if ($arNav[0]["ID"] == $arResult["ID"]) {
$arResult["PREV"] = $arNav[1];
} else {
$arResult["NEXT"] = $arNav[0];
}
}
?>
<?if($arResult["PREV"] || $arResult["NEXT"]):?>
<div class="news-navigation">
<?if($arResult["PREV"]):?>
<a href="<?=$arResult["PREV"]["DETAIL_PAGE_URL"]?>" class="prev-link">
<span class="arrow">←</span>
<span class="title"><?=$arResult["PREV"]["NAME"]?></span>
<?if($arResult["PREV"]["PREVIEW_PICTURE"]):?>
<img src="<?=CFile::GetPath($arResult["PREV"]["PREVIEW_PICTURE"])?>" alt="" class="preview-img">
<?endif;?>
</a>
<?endif;?>
<?if($arResult["NEXT"]):?>
<a href="<?=$arResult["NEXT"]["DETAIL_PAGE_URL"]?>" class="next-link">
<span class="title"><?=$arResult["NEXT"]["NAME"]?></span>
<span class="arrow">→</span>
<?if($arResult["NEXT"]["PREVIEW_PICTURE"]):?>
<img src="<?=CFile::GetPath($arResult["NEXT"]["PREVIEW_PICTURE"])?>" alt="" class="preview-img">
<?endif;?>
</a>
<?endif;?>
</div>
<?endif;?>Способ 3: Использование встроенных возможностей компонента
-
В параметрах компонента установите:
"SHOW_NAVIGATION" => "Y",
"PREV_LINK_NAME" => "Предыдущая новость",
"NEXT_LINK_NAME" => "Следующая новость",-
Для кастомизации создайте в шаблоне компонента файл
result_modifier.php:
<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
// Улучшаем навигацию
if ($arParams["SHOW_NAVIGATION"] == "Y") {
$arFilter = array(
"IBLOCK_ID" => $arResult["IBLOCK_ID"],
"ACTIVE" => "Y"
);
if ($arResult["IBLOCK_SECTION_ID"]) {
$arFilter["SECTION_ID"] = $arResult["IBLOCK_SECTION_ID"];
}
$res = CIBlockElement::GetList(
array("SORT" => "ASC", "ID" => "DESC"),
$arFilter,
false,
array("nElementID" => $arResult["ID"], "nPageSize" => 1),
array("ID", "NAME", "DETAIL_PAGE_URL")
);
$arNav = array();
while ($item = $res->GetNext()) {
$arNav[] = $item;
}
if (count($arNav) > 2) {
$arResult["PREV"] = $arNav[2];
$arResult["NEXT"] = $arNav[0];
}
}
?>Рекомендации по реализации
-
Производительность:
-
Всегда используйте кэширование
-
Ограничивайте выборку только нужными полями
-
Для больших инфоблоков используйте фильтрацию по разделам
-
-
UX улучшения:
-
Добавляйте превью изображений к навигации
-
Реализуйте микроразметку для SEO
-
Добавьте подсказки при наведении
-
-
SEO аспекты:
-
Используйте rel="prev" и rel="next" в ссылках
-
Добавьте микроразметку Schema.org
-
Обеспечьте корректные 301 редиректы при изменении URL
-
Пример микроразметки:
<div class="news-navigation" itemscope itemtype="http://schema.org/ItemList">
<?if($arPrev):?>
<a href="<?=$arPrev["DETAIL_PAGE_URL"]?>" itemprop="previousItem">
← <span itemprop="name"><?=$arPrev["NAME"]?></span>
</a>
<?endif;?>
<?if($arNext):?>
<a href="<?=$arNext["DETAIL_PAGE_URL"]?>" itemprop="nextItem">
<span itemprop="name"><?=$arNext["NAME"]?></span> →
</a>
<?endif;?>
</div>Заключение
Реализация навигации между новостями в Битрикс может быть как простой, так и достаточно сложной — в зависимости от требований проекта. Представленные в статье методы покрывают большинство типовых scenarios, от базовых до продвинутых.
Для дополнительной информации рекомендую обратиться к официальной документации: