WordPress как на ладони
wordpress jino

paginate_links() WP 2.1.0

Выводит ссылки пагинации для страниц архивов. Может быть использована для создания пагинации у любых страниц.

Технически функцию можно использовать для создания пагинации где угодно. Параметр base используется как ссылка на УРЛ, которая будет использована для создания ссылки пагинации. Параметр format будет заменен на номер пагинации. Эта функция является ядром для всех функций пагинации в WordPress.

Для построения пагинации в WordPress есть специальные фукнции-обертки для этой функции:

Параметр type контролирует в каком формате будет возвращен результат:

  • plain- просто ссылки разделенные переносом строки (По умолчанию).
  • array - в виде массива данных для дальнейшей обработки в PHP
  • list - <ul> список.

Числовой параметр total должен получить общее количество страниц пагинации, а параметр current номер текущей страницы пагинации. Пример параметра base - http://example.com/all_posts.php%_%, где %_% - обязательная часть, которая будет заменена тем что указано в параметре format. Пример format -  ?page=%#%, здесь %#%, также обязательная часть, которая будет заменена числом текущей страницы пагинации. Вообще, в base можно сразу указать например так: http://example.com/all_posts.php?page=%#%, а в формат пусто ('').

Чтобы добавить ссылки на предыдущую/следующую страницу, нужно включить логический параметр prev_next (указать ему true), а затем можно установить текст ссылок указав параметры prev_text/next_text  (предыдущая ссылка/следующая ссылка).

Если включить параметр show_all, то будут выведены абсолютно все ссылки пагинации, вместо нескольких ссылок вокруг текущей и нескольких конечных ссылок. По умолчанию, этот параметр выключен, а сколько ссылок показывать вокруг текущей страницы и на концах контролируется параметрами: end_size и mid_size.

Также есть возможность добавить в ссылки переменные запроса, для этого укажите нужные переменные и их значения в виде массива в параметр add_args. Подробнее см. функцию add_query_arg().

Параметры before_page_number и after_page_number позволяют обернуть само число пагинации, например в <span> для стилизации. А вообще, эти параметры были созданы для того, чтобы указать текст для роботов, чтобы при просмотре кода, было понятно для чего предназначены ссылки.

В результате вы получите нечто подобное: « предыдущая 1 … 3 4 5 6 7 … 9 следующая »

Хуки из функции:
Возвращает

HTML код.

Использование

<?php echo paginate_links( $args ) ?>

Шаблон использования

$args = array(
	'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 );
$args(строка/массив)
Аргументы для построения пагинации.
По умолчанию: предустановки

Аргументы параметра $args

base(строка)
База для замены по формату. В конструкции: http://example.com/all_posts.php%_% %_% будет заменено значением аргумента format (см. ниже).
По умолчанию: '%_%'
format(строка)
Формат замены.
По умолчанию: '?page=%#%'
total(число)
Общее количество страниц, которые участвуют в пагинации.
По умолчанию: 1
current(число)
Номер текущей страницы пагинации.
show_all(логический)
Если выставить в true, то в списке ссылок будут показаны все страницы участвующие в пагинации. По умолчанию показывается только несколько ссылок спереди и сзади номера текущей страницы, количество ссылок регулируется аргументами: end_size и mid_size.
По умолчанию: false
end_size(число)
Сколько номеров показывать сначала и конца ("предыдущая 12 ... 4 ... 89 следующая").
По умолчанию: 1
mid_size(число)
Сколько номеров показывать до и после текущего номера (... 123 5 678 ...).
По умолчанию: 2
prev_next(логический)
Выводить боковые ссылки "предыдущая/следующая страница". По умолчанию выводятся, если ненужно выводить эти ссылки пишем false.
По умолчанию: ture
prev_text(строка)
Текст ссылки "предыдущая страница".
По умолчанию: __('« Previous')
next_text(строка)
Текст ссылки "следующая страница".
По умолчанию: __('Next »')
type(строка)

Формат возвращаемых данных.

  • plain — строка ссылок разделенная пробелами. По умолчанию;

  • array — массив данных (для дальнейшей обработки);

  • list — html список <ul>.
    По умолчанию: 'plain'
add_args(логический)
Массив аргументов (переменных запроса), которые нужно добавить к ссылкам.
По умолчанию: false
add_fragment(строка)
Текст который добавиться ко всем ссылкам.
По умолчанию: ''

Примеры

#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 = str_replace( '/page/1/', '', $result );

	echo $result;
}

// Теперь, где нужно вывести пагинацию используем 
// my_pagenavi();

#2 Пример с произвольным запросом WP_Query

Когда записи получаются и выводятся отдельным запросом с помощью new WP_Query установите в параметр total свойство $max_num_pages. На примере:

Наш произвольный запрос и пагинация для него:

Это лишь демонстрационный пример, потому что он не учитывает основной запрос, в котором может получаться 404 страница и до этого кода дело вообще не дойдет.

<?php
// 1 значение по умолчанию
$paged = get_query_var( 'paged' ) ? absint( get_query_var( 'paged' ) ) : 1;

$the_query = new 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 ) ) ),
	'format'  => '?paged=%#%',
	'current' => max( 1, get_query_var('paged') ),
	'total'   => $the_query->max_num_pages
) );
?>

Код paginate links: wp-includes/general-template.php WP 4.8.2

<?php
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' ) ? intval( get_query_var( 'paged' ) ) : 1;

	// Append the format placeholder to the 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,
		'show_all' => false,
		'prev_next' => true,
		'prev_text' => __('&laquo; Previous'),
		'next_text' => __('Next &raquo;'),
		'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 found in the original URL into '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, to 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 in $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'];

		/**
		 * Filters the paginated links for the given archive pages.
		 *
		 * @since 3.0.0
		 *
		 * @param string $link The paginated link URL.
		 */
		$page_links[] = '<a class="prev page-numbers" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '">' . $args['prev_text'] . '</a>';
	endif;
	for ( $n = 1; $n <= $total; $n++ ) :
		if ( $n == $current ) :
			$page_links[] = "<span class='page-numbers current'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . "</span>";
			$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'];

				/** This filter is documented in wp-includes/general-template.php */
				$page_links[] = "<a class='page-numbers' href='" . esc_url( apply_filters( 'paginate_links', $link ) ) . "'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . "</a>";
				$dots = true;
			elseif ( $dots && ! $args['show_all'] ) :
				$page_links[] = '<span class="page-numbers dots">' . __( '&hellip;' ) . '</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'];

		/** This filter is documented in wp-includes/general-template.php */
		$page_links[] = '<a class="next page-numbers" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '">' . $args['next_text'] . '</a>';
	endif;
	switch ( $args['type'] ) {
		case 'array' :
			return $page_links;

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

		default :
			$r = join("\n", $page_links);
			break;
	}
	return $r;
}

Cвязанные функции

Из раздела: Архивы

paginate_links 36 комментариев
Полезные 1 Вопросы 2 Все
  • Serg

    Доброго времени суток всем. У меня вот такая функция отвечает за пагинацию.

    function the_acadp_pagination( $numpages = '', $pagerange = '', $paged = '' ) {
    
    	if( empty( $pagerange ) ) {
    		$pagerange = 2;
    	}
    
    	/**
    	 * This first part of our function is a fallback
    	 * for custom pagination inside a regular loop that
    	 * uses the global $paged and global $wp_query variables.
    	 * 
    	 * It's good because we can now override default pagination
    	 * in our theme, and use this function in default quries
    	 * and custom queries.
    	 */
    	if( empty( $paged ) ) {
    		$paged = acadp_get_page_number();
    	}
    
    	if( $numpages == '' ) {
    		global $wp_query;
    
    		$numpages = $wp_query->max_num_pages;
    		if( ! $numpages ) {
    			$numpages = 1;
    		}
    	}
    
    	/** 
    	 * We construct the pagination arguments to enter into our paginate_links
    	 * function. 
    	 */
    	$arr_params = array( 'order', 'sort', 'view', 'lang' );
    
    	$base = acadp_remove_query_arg( $arr_params, get_pagenum_link( 1 ) );
    
    	if( ! get_option('permalink_structure') || isset( $_GET['q'] ) ) {
    		$prefix = strpos( $base, '?' ) ? '&' : '?';
    		$format = $prefix.'paged=%#%';
    	} else {
    		$prefix = ( '/' == substr( $base, -1 ) ) ? '' : '/';
    		$format = $prefix.'page/%#%';
    	} 
    
    	$pagination_args = array(
    		'base'         => $base . '%_%',
    		'format'       => $format,
    		'total'        => $numpages,
    		'current'      => $paged,
    		'show_all'     => false,
    		'end_size'     => 0,
    		'mid_size'     => $pagerange,
    		'prev_next'    => true,
    		'prev_text'    => __( '«' ),
    		'next_text'    => __( '»' ),
    		'type'         => 'array',
    		'add_args'     => false,
    		'add_fragment' => ''
    	);
    
    	$paginate_links = paginate_links( $pagination_args );
    
    	if( $paginate_links ) {
    		echo " ";
    
    		echo "";
    		printf( __( "Page %d of %d", 'advanced-classifieds-and-directory-pro' ), $paged, $numpages );
    		echo "";
    
    		//echo "";          
    		foreach ( $paginate_links as $key => $page_link ) {
    
    			if( strpos( $page_link, 'current' ) !== false ) {
    				echo ''.$page_link.'';
    			} else {
    				echo ''.$page_link.'';
    			}
    
    		}
    		//echo "";
    
    		echo "";
    	}
    
    }

    Так выводится -

    <?php the_acadp_pagination( $acadp_query->max_num_pages, "", $paged ); ?>

    В связи с тем, что использую бутстрап-4 не могу подключить нужный класс ссылкам пагинации, помогите советом, где копать, мб как-нить показать только предыдущую и следующую или как нужный класс в ссылку прописать. За ранее благодарю.

    Ответить3 месяца назад #
    • Нашел такой велосипед, хотя и рабочий, но мне не нравится

      // Bootstrap pagination for index and category pages
      // if ( function_exists('b4st_pagination') ) b4st_pagination();
      // 
      if ( ! function_exists( 'b4st_pagination' ) ) {
        function b4st_pagination( $query=null ) {
      	global $wp_query;
      	$query = $query ? $query : $wp_query;
      	$big = 999999999; // This needs to be an unlikely integer
      	// For more options and info view the docs for paginate_links()
      	// http://codex.wordpress.org/Function_Reference/paginate_links
      	$paginate_links = paginate_links( array(
      	  'base' => str_replace( $big, '%#%', get_pagenum_link($big) ),
      	  'current' => max( 1, get_query_var('paged') ),
      	  'total' => $wp_query->max_num_pages,
      	  'mid_size' => 5,
      	  'prev_next' => false,
      	  'prev_text' => __('‹ previos', 'lang'),
      	  'next_text' => __('next ›', 'lang'),
      	  'type' => 'list'
      	) );
      	$paginate_links = str_replace( "<ul class='page-numbers'>", "<ul class='pagination mt-3 justify-content-center'>", $paginate_links );
      	$paginate_links = str_replace( "<li><span class='page-numbers current'>", "<li class='page-item active'><a class='page-link' onclick='return false' href='#'>", $paginate_links );
      	$paginate_links = str_replace( "<li>", "<li class='page-item'>", $paginate_links );
      	$paginate_links = str_replace( "<a", "<a class='page-link' ", $paginate_links );
      	$paginate_links = str_replace( "</span>", "</a>", $paginate_links );
      	$paginate_links = preg_replace( "/\s*page-numbers/", "", $paginate_links );
      
      	// Display the pagination if more than one page is found
      	if ( $query->max_num_pages > 1 ) {
      	  echo '<nav aria-label="Page navigation">';
      	  echo $paginate_links;
      	  echo '</nav>';
      	}
        }
      }
      Ответить28 дней назад #
    • Или же такой вариант допиленой пагинации от Тимура:

      /**
       * Альтернатива wp_pagenavi. Создает ссылки пагинации на страницах архивов.
       *
       * @param string $before   - текст до навигации
       * @param string $after    - текст после навигации
       * @param bool   $echo     - возвращать или выводить результат
       * @param array  $args     - аргументы функции
       * @param array  $wp_query - объект WP_Query на основе которого строится пагинация. По умолчанию глобальная переменная $wp_query
       *
       * Версия: 2.5.1
       * Автор: Тимур Камаев
       * Ссылка на страницу функции: http://wp-kama.ru/?p=8
       */
      function kama_pagenavi( $before = '', $after = '', $echo = true, $args = array(), $wp_query = null ) {
        if( ! $wp_query ){
      	wp_reset_query();
      	global $wp_query;
        }
      
        // параметры по умолчанию
        $default_args = array(
      	'text_num_page'   => '', // Текст перед пагинацией. {current} - текущая; {last} - последняя (пр. 'Страница {current} из {last}' получим: "Страница 4 из 60" )
      	'num_pages'       => 10, // сколько ссылок показывать
      	'step_link'       => 10, // ссылки с шагом (значение - число, размер шага (пр. 1,2,3...10,20,30). Ставим 0, если такие ссылки не нужны.
      	'dotright_text'   => '…', // промежуточный текст "до".
      	'dotright_text2'  => '…', // промежуточный текст "после".
      	'back_text'       => __('« previous', 'lang'), // текст "перейти на предыдущую страницу". Ставим 0, если эта ссылка не нужна.
      	'next_text'       => __('next »', 'lang'), // текст "перейти на следующую страницу". Ставим 0, если эта ссылка не нужна.
      	'first_page_text' => __('« first', 'lang'), // текст "к первой странице". Ставим 0, если вместо текста нужно показать номер страницы.
      	'last_page_text'  => __('last »', 'lang'), // текст "к последней странице". Ставим 0, если вместо текста нужно показать номер страницы.
      	'prev_next'       => true
        );
      
        $default_args = apply_filters('kama_pagenavi_args', $default_args ); // чтобы можно было установить свои значения по умолчанию
      
        $args = array_merge( $default_args, $args );
      
        extract( $args );
      
        $posts_per_page = (int) $wp_query->get('posts_per_page');
        $paged          = (int) $wp_query->get('paged');
        $max_page       = $wp_query->max_num_pages;
      
        //проверка на надобность в навигации
        if( $max_page <= 1 )
      	return false;
      
        if( empty( $paged ) || $paged == 0 )
      	$paged = 1;
      
        $pages_to_show = intval( $num_pages );
        $pages_to_show_minus_1 = $pages_to_show-1;
      
        $half_page_start = floor( $pages_to_show_minus_1/2 ); //сколько ссылок до текущей страницы
        $half_page_end = ceil( $pages_to_show_minus_1/2 ); //сколько ссылок после текущей страницы
      
        $start_page = $paged - $half_page_start; //первая страница
        $end_page = $paged + $half_page_end; //последняя страница (условно)
      
        if( $start_page <= 0 )
      	$start_page = 1;
        if( ($end_page - $start_page) != $pages_to_show_minus_1 )
      	$end_page = $start_page + $pages_to_show_minus_1;
        if( $end_page > $max_page ) {
      	$start_page = $max_page - $pages_to_show_minus_1;
      	$end_page = (int) $max_page;
        }
      
        if( $start_page <= 0 )
      	$start_page = 1;
      
        //выводим навигацию
        $out = '';
      
        // создаем базу чтобы вызвать get_pagenum_link один раз
        $link_base = str_replace( 99999999, '___', get_pagenum_link( 99999999 ) );
        $first_url = get_pagenum_link( 1 );
        if( false === strpos( $first_url, '?') )
      	$first_url = user_trailingslashit( $first_url );
      
        $out .= $before . '<nav aria-label="Page navigation"><ul class="pagination mt-3 justify-content-center">';
      
      	if( $text_num_page ){
      	  $text_num_page = preg_replace( '!{current}|{last}!', '%s', $text_num_page );
      	  $out.= sprintf( "<li class='page-item'><span class='page-link'>$text_num_page</span></li> ", $paged, $max_page );
      	}
      	// назад
      	if ( $back_text && $paged != 1 )
      	  $out .= '<li class="page-item"><a class="page-link prev" href="'. ( ($paged-1)==1 ? $first_url : str_replace( '___', ($paged-1), $link_base ) ) .'">'. $back_text .'</a></li> ';
      	// в начало
      	if ( $start_page >= 2 && $pages_to_show < $max_page ) {
      	  $out.= '<li class="page-item"><a class="page-link first" href="'. $first_url .'">'. ( $first_page_text ? $first_page_text : 1 ) .'</a></li> ';
      	  if( $dotright_text && $start_page != 2 ) $out .= '<li class="page-item"><span class="page-link extend">'. $dotright_text .'</span></li> ';
      	}
      	// пагинация
      	for( $i = $start_page; $i <= $end_page; $i++ ) {
      	  if( $i == $paged )
      		$out .= '<li class="page-item active"><span class="page-link">'.$i.'</span></li> ';
      	  elseif( $i == 1 )
      		$out .= '<li class="page-item"><a class="page-link" href="'. $first_url .'">1</a></li> ';
      	  else
      		$out .= '<li class="page-item"><a class="page-link" href="'. str_replace( '___', $i, $link_base ) .'">'. $i .'</a></li> ';
      	}
      
      	//ссылки с шагом
      	$dd = 0;
      	if ( $step_link && $end_page < $max_page ){
      	  for( $i = $end_page+1; $i<=$max_page; $i++ ) {
      		if( $i % $step_link == 0 && $i !== $num_pages ) {
      		  if ( ++$dd == 1 )
      			$out.= '<li class="page-item"><span class="page-link extend">'. $dotright_text2 .'</span></li> ';
      		  $out.= '<li class="page-item"><a class="page-link" href="'. str_replace( '___', $i, $link_base ) .'">'. $i .'</a></li> ';
      		}
      	  }
      	}
      	// в конец
      	if ( $end_page < $max_page && $default_args['prev_next'] ) {
      	  if( $dotright_text && $end_page != ($max_page-1) )
      		$out.= '<li class="page-item"><span class="page-link extend">'. $dotright_text2 .'</span></li> ';
      	  $out.= '<li class="page-item"><a class="page-link last" href="'. str_replace( '___', $max_page, $link_base ) .'">'. ( $last_page_text ? $last_page_text : $max_page ) .'</a></li> ';
      	}
      	// вперед
      	if ( $next_text && $paged != $end_page && $default_args['prev_next'] )
      	  $out.= '<li class="page-item"><a class="page-link next" href="'. str_replace( '___', ($paged+1), $link_base ) .'">'. $next_text .'</a></li> ';
      
      	$out .= "</ul></nav>". $after ."\n";
      
        $out = apply_filters('kama_pagenavi', $out );
      
        if( $echo )
      	return print $out;
      
        return $out;
      }
      /**
       * 2.5 - 2.5.1 - автоматический сброс основного запроса.
       */
      1
      Ответить28 дней назад #
  • Alexandrox @

    Доброе время! Будет ли работать эта функция в связке с Page-list от Webvitaly? Т.е. для создания пагинации страниц (а не записей)?

    Ответить13 дней назад #

Здравствуйте, !

Ваш комментарий