Альтернатива функции paginate_links()
для постраничной навигации
Функция paginate_links()
всегда возвращает HTML-код. Даже если вы укажете параметр type=array
, в результате получите массив готовых тегов <a>
. Это может не подойти, если вам нужно полностью изменить структуру HTML для постраничной навигации. Ниже приведена небольшая функция, которая возвращает массив объектов вместо HTML.
Функция для генерации ссылок постраничной навигации
/**
* Генерирует массив ссылок для постраничной навигации.
*
* @param array $args {
*
* @type int $total Максимально допустимое количество страниц.
* @type int $current Номер текущей страницы.
* @type string $url_base Шаблон URL. Ис��ользуйте {pagenum}
в качестве заглушки.
* @type string $first_url URL для первой страницы. По умолчанию: '' - автоматически берётся из $url_base.
* @type int $mid_size Количество ссылок до и после текущей: 1 ... 1 2 [3] 4 5 ... 99. По умолчанию: 2.
* @type int $end_size Количество ссылок в начале и в конце: 1 2 ... 3 4 [5] 6 7 ... 98 99. По умолчанию: 1.
* @type bool $show_all true - Показывать все ссылки. По умолчанию: false.
* @type string $a_text_patt %s
будет заменено на номер страницы. По умолчанию: '%s'
.
* @type bool $is_prev_next Нужно ли показывать ссылки на предыдущую и следующую страницы. По умолчанию: false.
* @type string $prev_text По умолчанию: « Предыдущая
.
* @type string $next_text По умолчанию: Следующая »
.
* }
*
* @return array
*/
function kama_paginate_links_data( array $args ): array {
global $wp_query;
// Устанавливаем значения по умолчанию
$args += [
'total' => 1,
'current' => 0,
'url_base' => '/{pagenum}',
'first_url' => '',
'mid_size' => 2,
'end_size' => 1,
'show_all' => false,
'a_text_patt' => '%s',
'is_prev_next' => false,
'prev_text' => '« Предыдущая',
'next_text' => 'Следующая »',
];
$rg = (object) $args;
$total_pages = max( 1, (int) ( $rg->total ?: $wp_query->max_num_pages ) );
if( $total_pages === 1 ){
return [];
}
// Корректируем параметры
$rg->total = $total_pages;
$rg->current = max( 1, abs( $rg->current ?: get_query_var( 'paged', 1 ) ) );
// Определяем базовый URL
$rg->url_base = $rg->url_base ?: str_replace( PHP_INT_MAX, '{pagenum}', get_pagenum_link( PHP_INT_MAX ) );
$rg->url_base = wp_normalize_path( $rg->url_base );
if( ! $rg->first_url ){
$rg->first_url = preg_replace( '~/paged?/{pagenum}/?|[?]paged?={pagenum}|/{pagenum}/?~', '', $rg->url_base );
$rg->first_url = user_trailingslashit( $rg->first_url );
}
// Основной массив
if( $rg->show_all ){
$active_nums = range( 1, $rg->total );
}
else {
// Расчет активных номеров
if( $rg->end_size > 1 ){
$start_nums = range( 1, $rg->end_size );
$end_nums = range( $rg->total - ($rg->end_size - 1), $rg->total );
}
else {
$start_nums = [ 1 ];
$end_nums = [ $rg->total ];
}
$from = $rg->current - $rg->mid_size;
$to = $rg->current + $rg->mid_size;
if( $from < 1 ){
$to = min( $rg->total, $to + absint( $from ) );
$from = 1;
}
if( $to > $rg->total ){
$from = max( 1, $from - ($to - $rg->total) );
$to = $rg->total;
}
$active_nums = array_merge( $start_nums, range( $from, $to ), $end_nums );
$active_nums = array_unique( $active_nums );
$active_nums = array_values( $active_nums ); // Обнуляем ключи
}
// Заполнение основного массива
$pages = [];
if( 1 === count( $active_nums ) ){
return $pages;
}
// Функция для получения информации о странице
$item_data = static function( $num ) use ( $rg ){
$data = [
'is_current' => false,
'page_num' => null,
'url' => null,
'link_text' => null,
'is_prev_next' => false,
'is_dots' => false,
];
if( 'dots' === $num ){
return (object) ( [
'is_dots' => true,
'link_text' => '…',
] + $data );
}
// Проверка на предыдущую и следующую страницы
$is_prev = 'prev' === $num && ( $num = max( 1, $rg->current - 1 ) );
$is_next = 'next' === $num && ( $num = min( $rg->total, $rg->current + 1 ) );
$data = [
'is_current' => ! ( $is_prev || $is_next ) && $num === $rg->current,
'page_num' => $num,
'url' => 1 === $num ? $rg->first_url : str_replace( '{pagenum}', $num, $rg->url_base ),
'is_prev_next' => $is_prev || $is_next,
] + $data;
if( $is_prev ){
$data['link_text'] = $rg->prev_text;
}
elseif( $is_next ) {
$data['link_text'] = $rg->next_text;
}
else {
$data['link_text'] = sprintf( $rg->a_text_patt, $num );
}
return (object) $data;
};
foreach( $active_nums as $indx => $num ){
$pages[] = $item_data( $num );
// Установка точек
$next = $active_nums[ $indx + 1 ] ?? null;
if( $next && ($num + 1) !== $next ){
$pages[] = $item_data( 'dots' );
}
}
if( $rg->is_prev_next ){
$rg->current !== 1 && array_unshift( $pages, $item_data( 'prev' ) );
$rg->current !== $rg->total && $pages[] = $item_data( 'next' );
}
return $pages;
}
Пример работы функции
$links_data = kama_paginate_links_data( [
'total' => 3,
'current' => 2,
'url_base' => 'http://site.com/page-name/paged/{pagenum}',
'mid_size' => 2,
] );
print_r( $links_data );
/*
Array
(
[0] => stdClass Object
(
[is_current] =>
[page_num] => 288
[url] => http://site.com/page-name/paged/288
[is_prev_next] => 1
[link_text] => « Предыдущая
[is_dots] =>
)
[1] => stdClass Object
(
[is_current] =>
[page_num] => 1
[url] => http://site.com/page-name/
[is_prev_next] =>
[link_text] => 1
[is_dots] =>
)
[2] => stdClass Object
(
[is_dots] => 1
[link_text] => …
[is_current] =>
[page_num] =>
[url] =>
[is_prev_next] =>
)
[3] => stdClass Object
(
[is_current] =>
[page_num] => 285
[url] => http://site.com/page-name/paged/285
[is_prev_next] =>
[link_text] => 285
[is_dots] =>
)
[4] => stdClass Object
(
[is_current] =>
[page_num] => 286
[url] => http://site.com/page-name/paged/286
[is_prev_next] =>
[link_text] => 286
[is_dots] =>
)
[5] => stdClass Object
(
[is_current] => 1
[page_num] => 287
[url] => http://site.com/page-name/paged/287
[is_prev_next] =>
[link_text] => 287
[is_dots] =>
)
)
*/
Использование функции в цикле
3,
'current' => 2,
'url_base' => 'http://site.com/page-name/paged/{pagenum}',
] );
if( $links_data ){
?>
-
is_current ) { ?>
page_num ) ?>
page_num ) ?>
Результат работы
Эта функция позволяет более гибко управлять постраничной навигацией на вашем сайте, создавая кастомные ссылки и изменяя структуру вывода, если это необходимо.