paginate_links() WP 2.1.0

Дозволяє створити посилання пагінації для будь-яких сторінок.

Приклад того, як виглядає планація:« предыдущая 1 … 3 4 5 6 7 … 9 следующая »

Технічно функцію можна використовувати для створення пагінації будь-де. Ця функція є ядром для всіх функцій пагінації WordPress.

Для побудови пагінації в WordPress є також спеціальні функції (обгортки для цієї функції):

Ця функція жорстко додає всі $_GET параметри поточного запиту (поточної сторінки) посилання пагінації. Тому, наприклад, якщо вона використовується в обробнику AJAX запиту, всі URL в ній будуть містити поточні GET параметри. Тикет з цієї теми та обговорення нижче в коментарях .

Трохи про параметри

Параметр totalповинен отримати загальну кількість сторінок пагінації, а параметр currentномер поточної сторінки пагінації.

Приклад параметра basehttp://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> для стилізації.

Взагалі ці параметри були створені для того, щоб вказати текст для роботів, щоб при перегляді коду було зрозуміло для чого призначені посилання.

Приклади

3

#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

#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. Тому що c pageбуде перенаправлення зі сторінки пагінації на сам запис, а з pagedбуде 404 помилка на сторінці пагінації.

  • Для отримання номера сторінки пагінації замість звичного get_query_var( 'paged' )використовуємо get_query_var( 'page' ).

  • Цей код не буде працювати на сторінках, у яких контент ділитися на кілька сторінок тегом <!–nextpage–> , докладніше див тут .
1

#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>
0

#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.0Added the aria_current argument.

Код paginate_links() WP 6.0.2

function paginate_links( $args = '' ) {
	Global $wp_query, $wp_rewrite;

	// Setting up default values ​​based on the current URL.
	$pagenum_link = html_entity_decode( get_pagenum_link() );
	$url_parts = explode('?', $pagenum_link);

	// Get max pages and current page out of the current query, if available.
	$total = isset( $wp_query->max_num_pages ) ? $wp_query->max_num_pages: 1;
	$current = get_query_var('paged')? (int) get_query_var( 'paged') : 1;

	// Призначити формат місця розташування до base URL.
	$pagenum_link = trailingslashit( $url_parts[0] ) . '%_%';

	// URL base depends on permalink settings.
	$format = $wp_rewrite->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
	$format .= $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%';

	$defaults = array(
		'base' => $pagenum_link, // http://example.com/all_posts.php%_% : %_% is replaced by format (below).
		'format' => $format, // ?page=%#% : %#% is replaced by the page number.
		'total' => $total,
		'current' => $current,
		'aria_current' => 'page',
		'show_all' => false,
		'prev_next' => true,
		'prev_text' => __( '« Previous' ),
		'next_text' => __( 'Next »' ),
		'end_size' => 1,
		'mid_size' => 2,
		'type' => 'plain',
		'add_args' => array(), // Array of query args to add.
		'add_fragment' => '',
		'before_page_number' => '',
		'after_page_number' => '',
	);

	$ args = wp_parse_args ($ args, $ defaults);

	if ( ! is_array( $args['add_args'] ) ) {
		$args['add_args'] = array();
	}

	// Merge additional query vars наведено в original URL в 'add_args' array.
	if ( isset( $url_parts[1] ) ) {
		// Find the format argument.
		$format = explode( '?', str_replace( '%_%', $args['format'], $args['base'] ) );
		$format_query = isset($format[1])? $format[1] : '';
		wp_parse_str($format_query, $format_args);

		// Find the query args of the requested URL.
		wp_parse_str( $url_parts[1], $url_query_args );

		// Remove the format argument from the array of query arguments, avoid overwriting custom format.
		foreach ( $format_args as $format_arg => $format_arg_value ) {
			unset( $url_query_args[ $format_arg ] );
		}

		$args['add_args'] = array_merge( $args['add_args'], urlencode_deep( $url_query_args ) );
	}

	// Who knows what else people pass в $args.
	$total = (int) $args['total'];
	if ( $ total < 2 ) {
		return;
	}
	$current = (int) $args['current'];
	$end_size = (int) $args['end_size']; // Out of bounds? Make it the default.
	if ($ end_size < 1) {
		$ end_size = 1;
	}
	$mid_size = (int) $args['mid_size'];
	if ( $mid_size < 0 ) {
		$ mid_size = 2;
	}

	$add_args = $args['add_args'];
	$ r = '';
	$page_links = array();
	$dots = false;

	if ( $args['prev_next'] && $current && 1 < $current ) :
		$link = str_replace( '%_%', 2 == $current ? '' : $args['format'], $args['base'] );
		$link = str_replace( '%#%', $current - 1, $link);
		if ( $add_args ) {
			$link = add_query_arg($add_args, $link);
		}
		$link .= $args['add_fragment'];

		$page_links[] = sprintf(
			'<a class="prev page-numbers" href="%s">%s</a>',
			/**
			 * Filters paginated links для given archive pages.
			 *
			 * @ Since 3.0.0
			 *
			 * @param string $link The paginated link URL.
			 */
			esc_url( apply_filters( 'paginate_links', $link ) ),
			$args['prev_text']
		);
	endif;

	for ( $n = 1; $ n <= $ total; $ n++ ) :
		if ( $n == $current ) :
			$page_links[] = sprintf(
				'<span aria-current="%s" class="page-numbers current">%s</span>',
				esc_attr( $args['aria_current'] ),
				$args['before_page_number'] . number_format_i18n($n). $args['after_page_number']
			);

			$ dots = true;
		else :
			if ( $args['show_all'] || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $ total - $ end_size ) ) :
				$link = str_replace( '%_%', 1 == $n ? '' : $args['format'], $args['base'] );
				$link = str_replace( '%#%', $n, $link );
				if ( $add_args ) {
					$link = add_query_arg($add_args, $link);
				}
				$link .= $args['add_fragment'];

				$page_links[] = sprintf(
					'<a class="page-numbers" href="%s">%s</a>',
					/** Цей filter is documented в wp-includes/general-template.php */
					esc_url( apply_filters( 'paginate_links', $link ) ),
					$args['before_page_number'] . number_format_i18n($n). $args['after_page_number']
				);

				$ dots = true;
			elseif ( $dots && ! $args['show_all'] ) :
				$page_links[] = '<span class="page-numbers dots">' . __('…'). '</span>';

				$dots = false;
			endif;
		endif;
	endfor;

	if ( $args['prev_next'] && $current && $current < $total ) :
		$link = str_replace( '%_%', $args['format'], $args['base'] );
		$link = str_replace( '%#%', $current + 1, $link );
		if ( $add_args ) {
			$link = add_query_arg($add_args, $link);
		}
		$link .= $args['add_fragment'];

		$page_links[] = sprintf(
			'<a class="next page-numbers" href="%s">%s</a>',
			/** Цей filter is documented в wp-includes/general-template.php */
			esc_url( apply_filters( 'paginate_links', $link ) ),
			$args['next_text']
		);
	endif;

	switch ( $args['type'] ) {
		case 'array':
			return $page_links;

		case 'list':
			$r .= "<ul class='page-numbers'>nt<li>";
			$r .= implode( "</li>nt<li>", $page_links );
			$r .= "</li>n</ul>n";
			break;

		default:
			$r = implode("n", $page_links);
			break;
	}

	/**
	 * Filters HTML output paginated links for archives.
	 *
	 * @ Since 5.7.0
	 *
	 * @param string $r HTML output.
	 * @param array $args An array of arguments. See paginate_links()
	 * for information on accepted arguments.
	 */
	$r = apply_filters( 'paginate_links_output', $r, $args);

	return $r;
}

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *