paginate_links()
Дозволяє створити посилання пагінації для будь-яких сторінок.
Приклад того, як виглядає планація:« предыдущая 1 … 3 4 5 6 7 … 9 следующая »
Технічно функцію можна використовувати для створення пагінації будь-де. Ця функція є ядром для всіх функцій пагінації WordPress.
Для побудови пагінації в WordPress є також спеціальні функції (обгортки для цієї функції):
Ця функція жорстко додає всі $_GET параметри поточного запиту (поточної сторінки) посилання пагінації. Тому, наприклад, якщо вона використовується в обробнику AJAX запиту, всі URL в ній будуть містити поточні GET параметри. Тикет з цієї теми та обговорення нижче в коментарях .
Трохи про параметри
Параметр totalповинен отримати загальну кількість сторінок пагінації, а параметр currentномер поточної сторінки пагінації.
Приклад параметра base– http://example.com/all_posts.php%_%, де %_% буде замінено тим, що вказано в параметрі format = '?page=%#%', тут %#% буде замінено числом поточної сторінки пагінації.
Взагалі, baseможна відразу вказати наприклад так: http://example.com/all_posts.php?page=%#%, і при цьому format = ''(порожньо).
До посилання можна додати змінні запити , для цього вкажіть потрібні змінні та їх значення у вигляді масиву до параметра add_args. Докладніше див. функцію add_query_arg() .
Щоб додати посилання на попередню/наступну сторінку, потрібно включити логічний параметр prev_next(вказати йому true ), а потім можна встановити текст посилань, вказавши параметри prev_text / next_text(попереднє посилання/наступне посилання).
Хуки з функції
Повертає
Строку|Массив|null.
Шаблон використання
$args = [
'base' => '%_%',
'format' => '?page=%#%',
'total' => 1,
'current' => 0,
'show_all' => False,
'end_size' => 1,
'mid_size' => 2,
'prev_next' => True,
'prev_text' => __('« Previous'),
'next_text' => __('Next''),
'type' => 'plain',
'add_args' => False,
'add_fragment' => '',
'before_page_number' => '',
'after_page_number' => ''
];
echo paginate_links($args);Використання
paginate_links($args);
- $args
(рядок/масив) - Аргументи для побудови пагінації.
За замовчуванням: попереднє встановлення
Аргументи параметра $args
- base
(рядок) Базовий формат УРЛ, який буде використаний для створення посилання на пагінацію. Наприклад:
http://example.com/all_posts.php%_%тут%_%буде замінено значення аргументу format .Можна
baseвідразу вказати наприклад так:http://example.com/all_posts.php?page=%#%, і при цьому вказати порожній рядок вformat.За замовчуванням: ‘%_%’
- format
(рядок) - Формат заміни.
За замовчуванням: ‘?page=%#%’ - total
(число) - Загальна кількість сторінок, що беруть участь у пагінації.
За замовчуванням: 1 - current
(число) - Номер поточної сторінки пагінації.
- show_all
(логічний) - true – будуть показані всі сторінки, що беруть участь у пагінації.
false – (За замовчуванням) відображається лише кілька посилань попереду та позаду номера поточної сторінки. Кількість посилань регулюється параметрами
end_sizeта
mid_size.
Типово: false - end_size
(число) - Скільки посилань показати з початку та кінця:
"предыдущая 1 2 ... [4] ... 8 9 следующая".
За замовчуванням: 1 - mid_size
(число) - Скільки номерів показувати до та після поточного номера:
1 ... 2 3 [4] 5 6 ... 99.
За замовчуванням: 2 - prev_next
(логічний) - Виводити бічні посилання “попередня/наступна сторінка”. За промовчанням виводяться, якщо НЕ потрібно виводити ці посилання пишемо false.
Типово: true - prev_text
(рядок) - Текст посилання “Попередня сторінка”.
Типово: __(‘« Previous’) - next_text
(рядок) - Текст посилання “Наступна сторінка”.
Типово: __(‘Next »’) - type
(рядок) Контролює в якому форматі буде повернено результат:
plain– просто посилання розділені пробілом (За замовчуванням).array– у вигляді масиву даних для подальшої обробки PHP.list– <ul> список.
Типово: ‘plain’
- add_args
(масив) - Масив змінних запиту, які потрібно додати до посилань пагінації. функцію
add_query_arg() .
За замовчуванням: array() - add_fragment
(рядок) - Текст, який додається до всіх посилань.
За замовчуванням: ” - aria_current
(рядок) (WP 4.9) - Значення атрибуту
aria-current. Можливі значення: ‘page’, ‘step’, ‘location’, ‘date’, ‘time’, ‘true’, ‘false’.
Типово: ‘page’ . - before_page_number
(рядок) - Текст/рядок перед числом пагінації.
- after_page_number
(рядок) Текст/рядок після числа пагінації.
Параметри before_page_number та after_page_number дозволяють обернути саме число пагінації. Наприклад тег <span> для стилізації.
Взагалі ці параметри були створені для того, щоб вказати текст для роботів, щоб при перегляді коду було зрозуміло для чого призначені посилання.
Приклади
#1 Пагінація, аналог wp_pagenavi
Щоб додати пагінацію на сторінку результатів пошуку або сторінку архівів, використовуйте такий код:
function my_pagenavi() {
global $wp_query;
$ big = 999999999; // Унікальне число для заміни
$ args = array (
'base' => str_replace( $big, '%#%', get_pagenum_link( $big ) ),
'format' => '',
'current' => max( 1, get_query_var('paged') ),
'total' => $wp_query->max_num_pages,
);
$result = paginate_links( $args );
// видаляємо добавку до пагінації для першої сторінки
$result = preg_replace( '~/page/1/?(['"])~', '', $result );
echo $result;
}
// Тепер, де потрібно вивести пагінацію використовуємо
// my_pagenavi();#2 Пагінація для довільного запиту WP_Query
У прикладі нижче будемо виводити продукти WooCommerce (post_type=product) на окремій сторінці запису (post_type=post). Тобто. використовуватимемо довільний запит і зробимо для нього пагінацію.
// Запитуємо продукти
$query = New WP_Query([
'post_type' => 'product',
'posts_per_page' => 5,
'paged' => get_query_var( 'page' ),
]);
// Обробляємо отримані у запиті продукти, якщо вони є
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
// виводимо заголовок
the_title();
}
wp_reset_postdata();
}
// Виводимо пагінацію, якщо продуктів більше за запитану кількість
echo paginate_links([
'base' => user_trailingslashit( wp_normalize_path( get_permalink() .'/%#%/' ) ),
'current' => max( 1, get_query_var( 'page' ) ),
'total' => $query->max_num_pages,
]);Ми вказали виводити по 5 товарів, якщо їх, наприклад 22, буде виведено 5 елементів пагінації, у тому числі 4 будуть посиланнями такого виду:
Поточна сторінка, посилання не виводиться (5 продуктів) http://example.com/назва-запису/2/ (5 продуктів) http://example.com/назва-запису/3/ (5 продуктів) http://example.com/назва-запису/4/ (5 продуктів) http://example.com/назва-запису/5/ (2 продукти)
Зверніть увагу:
У параметрі
base, де формується вид посилання пагінації, не використовуються такі слова якpageабоpaged. Тому що cpageбуде перенаправлення зі сторінки пагінації на сам запис, а зpagedбуде 404 помилка на сторінці пагінації.Для отримання номера сторінки пагінації замість звичного
get_query_var( 'paged' )використовуємоget_query_var( 'page' ).- Цей код не буде працювати на сторінках, у яких контент ділитися на кілька сторінок тегом <!–nextpage–> , докладніше див тут .
#3 Альтернатива цієї функції
paginate_links() завжди повертає HTML, навіть якщо параметр type=arrayви отримаєте масив готових <a>тегів. Це може не підійти, коли потрібно повністю змінити HTML-структуру вашої пагінації. Нижче невелика функція, яка повертає масив об’єктів замість HTML.
/**
* Generates array of pagination links.
*
* @author Kama (wp-kama.com)
* @ Varsion 2.5
*
* @param array $args {
*
* @type int $total Maximum allowable pagination page.
* @type int $current Current page number.
* @type string $url_base URL pattern. Use `{pagenum}` placeholder.
* @type string $first_url URL на першу сторінку. Default: '' - така автоматичнавід $url_base.
* @type int $mid_size Номер links before/after current: 1 ... 1 2 [3] 4 5 ... 99. Default: 2.
* @type int $end_size Число повідомлень на написах: 1 2 ... 3 4 [5] 6 7 ... 98 99. Default: 1.
* @type bool $show_all true - Show all links. Default: false.
* @type string $a_text_patt `%s` will be replaced with number of pagination page. Default: ``%s'`.
* @type bool $is_prev_next Whether to show prev/next links. «Previou 1 2 [3] 4...99 Next». Default: false.
* @type string $prev_text Default: `Previous`.
* @type string $next_text Default: `Next'.
* }
*
* @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' => 'Previous',
'next_text' => 'Next»',
];
$rg = (object) $args;
$total_pages = max( 1, (int) ( $rg->total?: $wp_query->max_num_pages ) );
if( $total_pages === 1 ){
return [];
}
// fix working parameters
$rg->total = $total_pages;
$rg->current = max( 1, abs( $rg->current ?: get_query_var( 'paged', 1 ) )));
$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 ){
// /foo/page(d)/2 >>> /foo/ /foo?page(d)=2 >>> /foo/
$rg->first_url = preg_replace( '~/paged?/{pagenum}/?|[?]paged?={pagenum}|/{pagenum}/?~', '', $rg->url_base );
$rg->first_url = user_trailingslashit( $rg->first_url );
}
// core array
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 ); // reset keys
}
// fill by core array
$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);
// set dots
$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] => https://holder.loc/ua/coins/page/288
[is_prev_next] => 1
[link_text] => « Назад
[is_dots] =>
)
[1] => stdClass Object
(
[is_current] =>
[page_num] => 1
[url] => https://holder.loc/ru/coins/
[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] => https://holder.loc/ua/coins/page/285
[is_prev_next] =>
[link_text] => 285
[is_dots] =>
)
[4] => stdClass Object
(
[is_current] =>
[page_num] => 286
[url] => https://holder.loc/ua/coins/page/286
[is_prev_next] =>
[link_text] => 286
[is_dots] =>
)
[5] => stdClass Object
(
[is_current] => 1
[page_num] => 287
[url] => https://holder.loc/ua/coins/page/287
[is_prev_next] =>
[link_text] => 287
[is_dots] =>
)
)
*/Тепер використовуємо цю функцію у циклі:
<?php
$links_data = kama_paginate_links_data([
'total' => 3,
'current' => 2,
'url_base' => 'http://site.com/page-name/paged/{pagenum}',
]);
if( $links_data ){
?>
<ul>
<?php foreach( $links_data as $link ) { ?>
<li>
<?php if ( $link->is_dots ) { ?>
<span><?= $link->link_text ?></span>
<?php } elseif ( $link->is_current ) { ?>
<strong><?= $link->link_text ?></strong>
<?php } else { ?>
<a href="<?php esc_attr_e( $link->url ) ?>"><?php _e( $link->link_text ) ?></a>
<?php } ?>
</li>
<?php } ?>
</ul>
<?php
}Отримаємо:
<ul> <li> <a href="http://site.com/page-name/paged/1">1</a> </li> <li> <strong>2</strong> </li> <li> <a href="http://site.com/page-name/paged/3">3</a> </li> </ul>
#4 Приклад із довільним запитом WP_Query
Коли записи виводяться окремим запитом за допомогою new WP_Query для виведення пагінації, можна встановити параметр total, в якому вказати властивість WP_Query::$max_num_pages . Розглянемо приклад:
Це лише демонстраційний приклад, тому що він не враховує основного запиту, в якому може виходити 404 сторінка і до цього коду справа взагалі не дійде. Також він може працювати неправильно на окремій сторінці запису.
<?php
// 1 значення за замовчуванням
$paged = get_query_var('paged')? absint(get_query_var('paged')): 1;
$the_query = новий WP_Query( array(
'posts_per_page' => 5,
'category_name' => 'gallery',
'paged' => $paged,
)));
// цикл виведення отриманих записів
while( $the_query->have_posts() ){
$the_query->the_post();
?>
<!-- HTML кожного запису -->
<?php
}
wp_reset_postdata();
// пагінація для довільного запиту
$ big = 999999999; // Унікальне число
echo paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'current' => max( 1, get_query_var('paged') ),
'total' => $the_query->max_num_pages
)));
?>
нотатки
- Global. WP_Query. $wp_query WordPress Query object.
- Global. WP_Rewrite. $wp_rewrite WordPress rewrite component.
список змін
| З версії 2.1.0 | Введено. |
| З версії 4.9.0 | Added the aria_current argument. |