Битрикс. Постраничная навигация
18.12.2018
Теги: CMS • Битрикс • Буферизация • Компонент • Навигация • ПостраничнаяНавигация • СтароеЯдро
Постраничная навигация в Битрикс формируется и выводится с помощью системного компонента bitrix:system.pagenavigation
. Компонент разработан для использования совместно с другими компонентами и тесно связан с ними. Посмотрим, как можно использовать этот компонент для постраничного вывода списка элементов инфоблока.
Системный компонент bitrix:system.pagenavigation
if (!CModule::IncludeModule('iblock')) { ShowError('Модуль «Информационные блоки» не установлен'); } // какие поля элементов инфоблока выбираем $arSelect = array( 'ID', 'CODE', 'NAME', 'PREVIEW_TEXT', ); // условия выборки элементов инфоблока $arFilter = array( 'IBLOCK_ID' => 5, // идентификатор инфоблока 'IBLOCK_ACTIVE' => 'Y', // инфоблок должен быть активным 'SECTION_ID' => 16, // идентификатор раздела инфоблока 'INCLUDE_SUBSECTIONS' => 'Y', // включая элементы из подразделов 'SECTION_ACTIVE' => 'Y', // разделы элементов должны быть активными 'ACTIVE' => 'Y', // только активные элементы 'ACTIVE_DATE' => 'Y', // активные элементы с учетом даты ); // сортировка элементов $arSort = array( 'SORT' => 'ASC' ); // постраничная навигация $arNavParams = array( 'nPageSize' => 2, // количество элементов на странице 'bShowAll' => true, // показывать ссылку «Все элементы»? ); // выполняем запрос к базе данных $dbResult = CIBlockElement::GetList( $arSort, $arFilter, false, $arNavParams, $arSelect ); ob_start(); // начинаем буферизацию вывода $APPLICATION->IncludeComponent( 'bitrix:system.pagenavigation', '', array( 'NAV_TITLE' => 'Элементы', // поясняющий текст для постраничной навигации 'NAV_RESULT' => $dbResult, // результаты выборки из базы данных 'SHOW_ALWAYS' => false // показывать постраничную навигацию всегда? ) ); $navString = ob_get_clean(); // завершаем буферизацию вывода while ($arElement = $dbResult->Fetch()) { echo '<h2>'.$arElement['NAME'].'</h2>', PHP_EOL; echo '<p>'.$arElement['PREVIEW_TEXT'].'</p>', PHP_EOL; } // выводим постраничную навигацию echo $navString;
Шаблон .default
откровенно кошмарный, так что есть смысл использовать modern
или round
:
$APPLICATION->IncludeComponent( 'bitrix:system.pagenavigation', 'modern', array(/*...*/) );
$APPLICATION->IncludeComponent( 'bitrix:system.pagenavigation', 'round', array(/*...*/) );
Метод CDBResult::GetPageNavString()
Можно упростить наш код, используя метод GetPageNavString
класса CDBResult
:
if (!CModule::IncludeModule('iblock')) { ShowError('Модуль «Информационные блоки» не установлен'); } // какие поля элементов инфоблока выбираем $arSelect = array(/*...*/); // условия выборки элементов инфоблока $arFilter = array(/*...*/); // сортировка элементов $arSort = array(/*...*/); // постраничная навигация $arNavParams = array( 'nPageSize' => 2, // количество элементов на странице 'bShowAll' => true, // показывать ссылку «Все элементы»? ); // выполняем запрос к базе данных $dbResult = CIBlockElement::GetList( $arSort, $arFilter, false, $arNavParams, $arSelect ); // html-код постраничной навигации $navString = $dbResult->GetPageNavString( 'Элементы', // поясняющий текст 'modern', // имя шаблона false // показывать всегда? ); while ($arElement = $dbResult->Fetch()) { echo '<h2>'.$arElement['NAME'].'</h2>', PHP_EOL; echo '<p>'.$arElement['PREVIEW_TEXT'].'</p>', PHP_EOL; } // выводим постраничную навигацию echo $navString;
Как нетрудно догадаться, внутри метода GetPageNavString()
идет подключение системного компонента bitrix:system.pagenavigation
и весь вывод компонента записывается в буфер. В предыдущем примере мы делали это сами, а теперь просто вызываем метод GetPageNavString()
.
Метод CDBResult::NavStart()
Это устаревший способ организации постраничной навигации, использовать его не рекомендуется. Для начала выбираем все элементы инфоблока, попадающие под условия выборки, без постраничной навигации:
if (!CModule::IncludeModule('iblock')) { ShowError('Модуль «Информационные блоки» не установлен'); } // какие поля элементов инфоблока выбираем $arSelect = array(/*...*/); // условия выборки элементов инфоблока $arFilter = array(/*...*/); // сортировка элементов $arSort = array(/*...*/); // выполняем запрос к базе данных $dbResult = CIBlockElement::GetList( $arSort, $arFilter, false, false, // никаких ограничений выборки для постраничной навигации $arSelect ); while ($arElement = $dbResult->Fetch()) { echo '<h2>'.$arElement['NAME'].'</h2>', PHP_EOL; echo '<p>'.$arElement['PREVIEW_TEXT'].'</p>', PHP_EOL; }
Теперь добавим постраничную навигацию с помощью CAllDBResult::NavStart()
:
if (!CModule::IncludeModule('iblock')) { ShowError('Модуль «Информационные блоки» не установлен'); } // какие поля элементов инфоблока выбираем $arSelect = array(/*...*/); // условия выборки элементов инфоблока $arFilter = array(/*...*/); // сортировка элементов $arSort = array(/*...*/); // выполняем запрос к базе данных $dbResult = CIBlockElement::GetList( $arSort, $arFilter, false, false, // никаких ограничений выборки для постраничной навигации $arSelect ); /* * Кол-во элементов на странице 2, показывать ссылку «Все элементы» */ $dbResult->NavStart(2, true); while ($arElement = $dbResult->Fetch()) { echo '<h2>'.$arElement['NAME'].'</h2>', PHP_EOL; echo '<p>'.$arElement['PREVIEW_TEXT'].'</p>', PHP_EOL; } /* * Показываем постраничную навигацию */ $dbResult->NavPrint('Элементы');
CDBResult::NavStart( int page_size = 10, bool show_all = true )
Метод разбивает результат выборки на страницы. После вызова этого метода, методы
CDBResult::Fetch()
CDBResult::GetNext()
CDBResult::ExtractFields()
CDBResult::NavNext()
будут ограничены только текущей страницей (а не всей выборкой).
Постраничная навигация в компонентах
Добавить параметры постраничной навигации на страницу настройки компонента:
<?php /* * Файл local/components/tokmakov/iblock.section/.parameters.php */ if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die(); /* * Настройки компонента */ $arComponentParameters = array( /*...*/ ); // настройка постраничной навигации CIBlockParameters::AddPagerSettings( $arComponentParameters, 'Элементы', // $pager_title false, // $bDescNumbering true, // $bShowAllParam ); // добавляем еще одну настройку — на случай, если раздел инфоблока не найден CIBlockParameters::Add404Settings($arComponentParameters, $arCurrentValues);
Постраничная навигация в коде компонента:
<?php /* * Файл local/components/infoblock/iblock.section/component.php */ if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die(); if (!CModule::IncludeModule('iblock')) { ShowError('Модуль «Информационные блоки» не установлен'); return; } // запрещаем сохранение в сессии номера последней страницы // при стандартной постраничной навигации CPageOption::SetOptionString('main', 'nav_page_in_session', 'N'); if (!isset($arParams['CACHE_TIME'])) { $arParams['CACHE_TIME'] = 3600; } // тип инфоблока $arParams['IBLOCK_TYPE'] = trim($arParams['IBLOCK_TYPE']); // идентификатор инфоблока $arParams['IBLOCK_ID'] = intval($arParams['IBLOCK_ID']); // количество элементов на страницу $arParams['ELEMENT_COUNT'] = intval($arParams['ELEMENT_COUNT']); if ($arParams['ELEMENT_COUNT'] <= 0) { $arParams['ELEMENT_COUNT'] = 3; } // учитывать права доступа при кешировании? $arParams['CACHE_GROUPS'] = $arParams['CACHE_GROUPS']=='Y'; // показывать постраничную навигацию вверху списка элементов? $arParams['DISPLAY_TOP_PAGER'] = $arParams['DISPLAY_TOP_PAGER']=='Y'; // показывать постраничную навигацию внизу списка элементов? $arParams['DISPLAY_BOTTOM_PAGER'] = $arParams['DISPLAY_BOTTOM_PAGER']=='Y'; // поясняющий текст для постраничной навигации $arParams['PAGER_TITLE'] = trim($arParams['PAGER_TITLE']); // всегда показывать постраничную навигацию, даже если в этом нет необходимости $arParams['PAGER_SHOW_ALWAYS'] = $arParams['PAGER_SHOW_ALWAYS']=='Y'; // имя шаблона постраничной навигации $arParams['PAGER_TEMPLATE'] = trim($arParams['PAGER_TEMPLATE']); // показывать ссылку «Все элементы», с помощью которой можно показать все элементы списка? $arParams['PAGER_SHOW_ALL'] = $arParams['PAGER_SHOW_ALL']=='Y'; // получаем все параметры постраничной навигации, от которых будет зависеть кеш $arNavParams = null; $arNavigation = false; if ($arParams['DISPLAY_TOP_PAGER'] || $arParams['DISPLAY_BOTTOM_PAGER']) { $arNavParams = array( 'nPageSize' => $arParams['ELEMENT_COUNT'], // количество элементов на странице 'bShowAll' => $arParams['PAGER_SHOW_ALL'], // показывать ссылку «Все элементы»? ); $arNavigation = CDBResult::GetNavParams($arNavParams); } $cacheDependence = array($arParams['CACHE_GROUPS'] ? $USER->GetGroups() : false, $arNavigation); if ($this->StartResultCache(false, $cacheDependence)) { /* * Получаем информацию о разделе инфоблока */ // какие поля раздела инфоблока выбираем $arSelect = array(/*...*/); // условия выборки раздела инфоблока $arFilter = array(/*...*/); // выполняем запрос к базе данных $rsSection = CIBlockSection::GetList(array(), $arFilter, false, $arSelect); $arResult = $rsSection->GetNext(); if ($arResult) { /* * Получаем элементы этого раздела инфоблока */ // какие поля элементов выбираем $arSelect = array(/*...*/); // условия выборки элементов инфоблока $arFilter = array(/*...*/); // сортировка элементов $arSort = array(/*...*/); // выполняем запрос к базе данных $rsElements = CIBlockElement::GetList($arSort, $arFilter, false, $arNavParams, $arSelect); $arResult['ITEMS'] = array(); while ($arItem = $rsElements->GetNext()) { $arResult['ITEMS'][] = $arItem; } /* * Постраничная навигация */ $arResult['NAV_STRING'] = $rsElements->GetPageNavString( $arParams['PAGER_TITLE'], $arParams['PAGER_TEMPLATE'], $arParams['PAGER_SHOW_ALWAYS'], $this ); $this->SetResultCacheKeys( /*...*/ ); $this->IncludeComponentTemplate(); } else { // если раздел инфоблока не найден $this->AbortResultCache(); \Bitrix\Iblock\Component\Tools::process404(/*...*/); } } // кэш не затронет все действия ниже, здесь работаем уже с другим $arResult if (isset($arResult['ID'])) { /*...*/ }
Свой шаблон постраничной навигации
Чтобы кастомизировать постраничную навигацию, надо скопировать один из шаблонов системного компонента system.pagenavigation
. Все содержимое папки modern
копируем в папку pager
:
bitrix/components/bitrix/system.pagenavigation/templates/modern
local/templates/.default/components/bitrix/system.pagenavigation/pager
Удаляем файл стилей style.min.css
и создаем файл .description.php
:
<?php /* * Файл local/templates/.default/components/bitrix/system.navigation/pager/.description.php */ if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die(); $arTemplateDescription = array( "NAME" => GetMessage("SYS_PAGER_TMPL_NAME"), "DESCRIPTION" => GetMessage("SYS_PAGER_TMPL_DESCR"), );
<?php /* * Файл local/templates/.default/components/bitrix/system.navigation/pager/lang/ru/.description.php */ $MESS['SYS_PAGER_TMPL_NAME'] = 'Постраничная навигация'; $MESS['SYS_PAGER_TMPL_DESCR'] = 'Шаблон постраничной навигации';
И теперь нам надо отредактировать файл template.php
. Распечатаем массив $arResult
с помощью функции print_r()
:
Array ( [NavShowAlways] => [NavTitle] => Статьи [NavRecordCount] => 11 [NavPageCount] => 6 [NavPageNomer] => 3 [NavPageSize] => 2 [bShowAll] => [NavShowAll] => [NavNum] => 1 [bDescPageNumbering] => [add_anchor] => [nPageWindow] => 5 [bSavePage] => [sUrlPath] => /blog/ [NavQueryString] => [sUrlPathParams] => /blog/? [nStartPage] => 1 [nEndPage] => 5 [NavFirstRecordShow] => 5 [NavLastRecordShow] => 6 )
В нашем случае показывается список из 11 статей, по две статьи на страницу. Всего получается 6 страниц, но на последней странице только одна статья.
NavShowAlways
— всегда показывать постраничную навигациюNavTitle
— название списка элементов, например «Статьи» или «Новости»NavRecordCount
— общее количество статей (записей)NavPageCount
— общее количество страницNavPageNomer
— номер текущей страницыNavPageSize
— количество статей на одну страницуbShowAll
— разрешено или нет показывать ссылку «Все статьи»NavShowAll
— равенtrue
, если показываются все статьи, без постраничной навигацииNavNum
— номер постраничной навигации (PAGEN_1
,PAGEN_2
, …)bDescPageNumbering
— использовать или нет обратную постраничную навигациюnPageWindow
— количество страниц, которые отображаются в постраничной навигацииbSavePage
— равнаtrue
если в главном модуле отмечена опция «Запоминать последнюю открытую страницу»sUrlPath
— путь к странице относительно корняNavQueryString
— строка GET-параметровnStartPage
— номер первой страницы слева для текущей страницыnEndPage
— номер первой страница справа для текущей страницыNavFirstRecordShow
— порядковый номер первой статьи на текущей страницеNavLastRecordShow
— порядковый номер последней статьи на текущей странице
По поводу переменной bSavePage
:
// Пример запрещает сохранение в сессии номера последней страницы при стандартной // постраничной навигации. По умолчанию в сессии запоминается последняя открытая // страница постраничной навигации. CPageOption::SetOptionString("main", "nav_page_in_session", "N");
По поводу переменных nStartPage
и nEndPage
. Если текущая страница — третья (NavPageNomer=3
), а показывается пять ссылок (nPageWindow=5
), тогда nStartPage=1
, а nEndPage=5
:
<a href="...">1</a> <a href="...">2</a> <span>3</span> <a href="...">4</a> <a href="...">5</a>
Если текущая страница — четвертая (NavPageNomer=4
), а показывается пять ссылок (nPageWindow=5
), тогда nStartPage=2
, а nEndPage=6
:
<a href="...">2</a> <a href="...">3</a> <span>4</span> <a href="...">5</a> <a href="...">6</a>
NavFirstRecordShow
и NavLastRecordShow
. У нас всего 11 статей на 6 страницах, по две статьи на страницу. Если текщая страница — третья, то NavFirstRecordShow=5
, а NavLastRecordShow=6
. На первой странице будут первая и вторая статьи, на второй странице — третья и четвертая, на третьей странице (текущей) — пятая и шестая.
<?php /* * Файл local/templates/.default/components/bitrix/system.pagenavigation/pager/template.php */ if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die(); $this->setFrameMode(true); // ссылка на первую страницу $firstPageUrl = $arResult['sUrlPath']; if (!empty($arResult['NavQueryString'])) { $firstPageUrl = $firstPageUrl.'?'.$arResult['NavQueryString']; } // ссылка на последнюю страницу $lastPageUrl = $arResult['sUrlPath']; if (!empty($arResult['NavQueryString'])) { $lastPageUrl = $lastPageUrl.'?'.$arResult['NavQueryString'] .'&PAGEN_'.$arResult['NavNum'].'='.$arResult['NavPageCount']; } else { $lastPageUrl = $lastPageUrl.'?PAGEN_'.$arResult['NavNum'].'='.$arResult['NavPageCount']; } ?> <ul class="pager"> <?php if ($arResult['NavPageNomer'] > 1): /* ссылка на первую страницу */ ?> <li> <a href="<?= $firstPageUrl ?>" title="Первая">«</a> </li> <?php endif; ?> <?php for ($i = $arResult['nStartPage']; $i <= $arResult['nEndPage']; $i++): ?> <?php // ссылка на очередную страницу $pageUrl = $arResult['sUrlPath']; if (!empty($arResult['NavQueryString'])) { $pageUrl = $pageUrl.'?'.$arResult['NavQueryString'].'&PAGEN_'.$arResult['NavNum'].'='.$i; } else { $pageUrl = $pageUrl.'?PAGEN_'.$arResult['NavNum'].'='.$i; } ?> <?php if ($arResult['NavPageNomer'] == $i): /* если это текущая страница */ ?> <li><span><?= $i; ?></span></li> <?php else: ?> <li><a href="<?= $pageUrl; ?>"><?= $i; ?></a></li> <?php endif; ?> <?php endfor; ?> <?php if ($arResult['NavPageNomer'] < $arResult['NavPageCount']): /* ссылка на последнюю страницу */ ?> <li> <a href="<?= $lastPageUrl; ?>" title="Последняя">»</a> </li> <?php endif; ?> </ul>
/*
* Файл local/templates/.default/components/bitrix/system.pagenavigation/pager/style.css
*/
.pager {
overflow: hidden;
margin: 10px 0;
}
.pager li {
list-style: none;
float: left;
margin-right: 15px;
}
.pager li:last-child {
margin-right: 0;
}
.pager li a {
display: block;
width: 26px;
height: 26px;
text-align: center;
background: #395985;
font-size: 14px;
line-height: 26px;
color: #fff;
text-decoration: none;
}
.pager li span {
display: block;
width: 26px;
height: 26px;
text-align: center;
background: #e9751f;
font-size: 14px;
line-height: 26px;
color: #fff;
}
Дополнительно
Поиск: CMS • Битрикс • Буферизация • Компонент • Навигация • Постраничная навигация • Старое ядро • bitrix:system.pagenavigation • CDBResult • GetPageNavString • NavStart • NavPrint