Альтернатива плагіну WP-pagenavi (пагінація для WordPress)

З версії 4.1 у WordPress з’явилася рідна аналогічна функція: the_posts_pagination()

Попалася мені якось тема, що найпопулярніший плагін WordPress wp-pagenavi навантажує сервер не в міру власної потреби. Проаналізувавши його код з’ясував, що це лише міф, хоча його все ж таки можна трохи оптимізувати, власне цьому і присвячений пост.

Якщо інші плагіни складно уявити без можливості їх налаштування в адмін-панелі, wp-pagenavi мені представляється легко. Достатньо один раз налаштувати навігацію та забути про неї. І мабуть є ті, хто думає так само? Тому я вирішив відмовитися від wp-pagenavi та замінити його на свою функцію. Функцію я написав, попередньо вивчивши код wp-pagenavi, частково код узяли від туди. Всі CSS класи wp-pagenavi збережені і, як наслідок, замінити wp-pagenavi на мій варіант зовсім не важко.

Для заміни потрібно скопіювати нижченаведену функцію у файл шаблону functions.php. Також потрібно скопіювати CSS стилі wp-pagenavi у ваш файл стилів (зазвичай це style.css). Перенесення стилів має корисний характер, тому що більше не буде необхідності підключати файл стилів, а це мінус один http запит.

/**
 * Альтернатива wp_pagenavi. Створює посилання на пагінацію на сторінках архівів.
 *
 * @version 2.8
 * @author Тимур Камаєв
 * @ link https://wp-doc.com/8
 *
 * @param array $args Аргументи функції.
 * @param WP_Query $wp_query Об'єкт WP_Query на основі якого будується пагінація. За промовчанням глобальна змінна $wp_query.
 *
 * @return string Pagination HTML code.
 */
function kama_pagenavi( $args = [], $wp_query = null ){

	// Параметри за замовчуванням
	$default = [
		'before' => '', // Текст до навігації.
		'after' => '', // Текст після навігації.
		'echo' => true, // Повертати чи виводити результат.

		'text_num_page' => '', // Текст перед пагінацією.
		//{current} – поточна.
		// {last} - остання (пр: 'Сторінка {current} з {last}' отримаємо: "Сторінка 4 із 60").
		'num_pages' => 10 // Скільки посилань показувати.
		'step_link' => 10, // Посилання з кроком (якщо 10, то: 1,2,3 ... 10,20, 30. Ставимо 0, якщо такі посилання не потрібні.
		'dotright_text' => '…', // Проміжний текст "до".
		'dotright_text2' => '…', // Проміжний текст "після".
		'back_text' => '« назад', // Текст "перейти на попередню сторінку". Ставимо 0, якщо це посилання не потрібне.
		'next_text' => 'вперед», // Текст "перейти на наступну сторінку". Ставимо 0, якщо це посилання не потрібне.
		'first_page_text' => '« на початок', // Текст "до першої сторінки". Ставимо 0, якщо замість тексту потрібно показати номер сторінки.
		'last_page_text' => 'наприкінці »', // Текст "до останньої сторінки". Ставимо 0, якщо замість тексту потрібно показати номер сторінки.
	];

	// Сумісність з v2.5: kama_pagenavi( $before = '', $after = '', $echo = true, $args = array() )
	$fargs = func_get_args();
	if( $fargs && is_string( $fargs[0] ) ){
		$default['before'] = isset($fargs[0]) ? $fargs[0] : '';
		$default['after'] = isset($fargs[1]) ? $fargs[1] : '';
		$default['echo'] = isset($fargs[2]) ? $ fargs [2] : true;
		$args = isset($fargs[3]) ? $fargs[3] : array();
		$wp_query = $GLOBALS['wp_query']; // Після визначення $ default!
	}

	if( ! $wp_query ){
		wp_reset_query();
		global $wp_query;
	}

	if( ! $args ){
		$args = [];
	}

	if( $args instanceof WP_Query ){
		$wp_query = $args;
		$args = [];
	}

	/**
	 * Дозволяє встановити параметри за замовчуванням.
	 *
	 * @param array $default_args
	 */
	$default = apply_filters( 'kama_pagenavi_args', $default );

	$ rg = (object) array_merge ($ default, $ args);

	$paged = (int) $wp_query->get( 'paged' )?: 1;
	$max_page = $wp_query->max_num_pages;

	// navigation no needed
	if( $max_page < 2 ){
		return '';
	}

	$pages_to_show = (int) $rg->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;
	}

	// створюємо базу, щоб викликати get_pagenum_link один раз
	$link_base = str_replace( PHP_INT_MAX, '___', get_pagenum_link( PHP_INT_MAX ) );
	$first_url = get_pagenum_link(1);
	if( false === strpos( $first_url, '?' ) ){
		$first_url = user_trailingslashit( $first_url );
	}

	// збираємо елементи
	$els = [];

	if( $rg->text_num_page ){
		$rg->text_num_page = preg_replace( '!{current}|{last}!', '%s', $rg->text_num_page );
		$els['pages'] = sprintf( '<span class="pages">' . $rg->text_num_page . '</span>', $paged, $max_page );
	}
	// назад
	if( $rg->back_text && $paged !== 1 ){
		$els['prev'] = '<a class="prev" href="' ( $paged - 1 ) == 1 ? $first_url : str_replace( '___', ) ) . $rg->back_text . '</a>';
	}
	// на початок
	if( $start_page >= 2 && $pages_to_show < $max_page ){
		$els['first'] = '<a class="first" href="' . $first_url . '">' . ($rg->first_page_text?: 1). '</a>';
		if( $rg->dotright_text && $start_page !== 2 ){
			$els[] = '<span class="extend">' . $rg->dotright_text . '</span>';
		}
	}
	// пагінація
	for( $i = $start_page; $i <= $end_page; $i++ ){
		if( $i === $paged ){
			$els['current'] = '<span class="current">' . $i . '</span>';
		}
		elseif( $i === 1 ){
			$els[] = '<a href="' . $first_url . '">1</a>';
		}
		else {
			$els[] = '<a href="' . str_replace( '___', $i, $link_base ) . '">' . $i . '</a>';
		}
	}

	// Посилання з кроком
	$dd = 0;
	if( $rg->step_link && $end_page < $max_page ){
		for( $i = $end_page + 1; $i <= $max_page; $i++ ){
			if( 0 === ( $i % $rg->step_link) && $i !== $rg->num_pages ){
				if( ++$dd === 1 ){
					$els[] = '<span class="extend">' . $rg->dotright_text2 . '</span>';
				}
				$els[] = '<a href="' . str_replace( '___', $i, $link_base ) . '">' . $i . '</a>';
			}
		}
	}
	// в кінець
	if( $end_page < $max_page ){
		if( $rg->dotright_text && $end_page !== ( $max_page - 1 ) ){
			$els[] = '<span class="extend">' . $rg->dotright_text2 . '</span>';
		}
		$els['last'] = sprintf( '<a class="last" href="%s">%s</a>',
			str_replace( '___', $max_page, $link_base ),
			$rg->last_page_text?: $max_page
		);
	}
	// Вперед
	if( $rg->next_text && $paged !== $end_page ){
		$els['next'] = sprintf( '<a class="next" href="%s">%s</a>',
			str_replace( '___', ( $paged + 1 ), $link_base ),
			$rg->next_text
		);
	}

	/**
	 * Allow to change pagenavi elements.
	 *
	 * @param array $elements
	 */
	$els = apply_filters( 'kama_pagenavi_elements', $els );

	$html = $rg->before . '<div class="wp-pagenavi">' . implode('', $els). '</div>'. $rg->after;

	/**
	 * Allow to change final output HTML code of pagenavi.
	 *
	 * @param array $html
	 */
	$html = apply_filters( 'kama_pagenavi', $html);

	if( ! $rg->echo ){
		return $html;
	}

	echo $html;
}

/**
 * CHANGELOG:
 *
 * 2.8 (14.02.2022)
 * - Minor improvements.
 * 2.7 (02.11.2018)
 * - У $args можна вказати другий параметр $wp_query, коли $args можна залишити порожнім.
 * - Виправлення коду - виправив баги, переробив збирання елементів у масив.
 * - Новий хук `kama_pagenavi_elements`.
 * 2.6 (20.10.2018)
 * - Прибрав extract().
 * - Переніс параметри $before, $after, $echo у $args (старий варіант буде працювати).
 * 2.5 - 2.5.1
 * - Автоматичне скидання основного запиту.
 */

Налаштування описані прямо в коді і вони ідентичні налаштуванням wp-pagenavi, з тією різницею, що замість тексту “до останньої сторінки” можна вивести номер останньої сторінки.

Після того, як функція встановлена ​​та css стилі перенесені, змінюємо в шаблоні код wp_pagenavi на цей:

<?php kama_pagenavi(); ?>

Якщо у вас в коді щось подібне до цього, то потрібно поміняти все wp_pagenavi на kama_pagenavi :

if(function_exists('wp_pagenavi')) {
	wp_pagenavi( '<center>', '</center>' );
}

CSS стилі для коду

Вище я вже сказав. що класи CSS збігаються з wp-pagenavi. Для зручності викладаю тут всі CSS правила:

.wp-pagenavi{ margin:2em auto; text-align:center; }
.wp-pagenavi > *{ display:inline-block; padding:.0em .5em; margin:.1em; border:1px solid #93a8bc; border-radius:3px; color:#465366; }
.wp-pagenavi a,
	.wp-pagenavi a:hover{ text-decoration:none; }
.wp-pagenavi a {background-color: #FFFFFF; }
.wp-pagenavi a:hover{ border-color:#7d95ac; }
.wp-pagenavi .pages{ }
. wp-pagenavi . current { border-color: # 465366; color: #465366; }
.wp-pagenavi .extend{ color: #465366; }
.wp-pagenavi .first{ }
.wp-pagenavi .last{ }
.wp-pagenavi .prev{ border-color:rgba(0,0,0,0); }
.wp-pagenavi .next { border-color: rgba (0,0,0,0); }

У моєму коді є 4 нових класи: first (на початок), last (на кінець), prev (назад), next (вперед).

Непогану добірку стилів можна взяти тут .

Якщо навігація виводиться 2 рази

Також хочу звернути увагу тих, у кого навігація виводиться 2 рази на сторінці (згори і знизу циклу). Щоб 2 рази не виконувати одні й самі операції зі складання навігації, логічніше зробити так: один раз зібрати навігацію (використовувати функцію), потім записати результат у змінну і вдруге просто вивести цю змінну. Виглядає це так:

// Місце, де вперше потрібно вивести навігацію
// Отримуємо навігацію і записуємо її в змінну
$navigation = kama_pagenavi('', '', false);
// Виводимо змінну на екран
echo $navigation;

		/* Тут йде висновок постів - цикл Loop */

// Місце, де вдруге необхідно вивести навігацію.
/ / Оскільки навігація вже записана в змінну $ get_navigation, її можна просто вивести на екран.
echo $navigation;

Оновлення

17 грудня 2013
Версія 2.0. Підправив код, прибрав зайві, непотрібні виклики функції get_pagenum_link(), за рахунок чого код почав працювати набагато швидше без втрати якості.

11 травня 2010
Переніс посилання назад/вперед , тепер так: «назад « ** на початок 11 12 13 14 15 16 17 18 в кінець ** » вперед»

Останній варіант функції нагорі .

2 травня 2010

  1. Додані посилання назад/вперед, приклад:
    « ** на початок “назад11 12 13 14 15 16 17 18 вперед» в кінець ** » Їх можна вимкнути (див. налаштування).

  2. Прибрано баг такого типу:
    1 2 3 4 5 6 7 850 або 121 22 23 24 25 26 27 28 29
    Тобто, де не потрібно прибрано тексти ” до ” і ” після ” навігації (в даному прикладі це трикрапка).

Реверсивна пагінація для WordPress

Ідея реверсивної (зворотної) пагінації належить sholo , який висловив її на відомому нам форумі – mywordpress.ru . Мені стало цікаво подивитися, як це виглядатиме і я трохи переробив код.

Цей код базується на старій версії основного коду.

/* Альтернатива wp_pagenavi - реверсивна пагінація
-------------------------------------------------- ------------------------------- */
function kama_pagenavi($before='', $after='', $echo=true) {
	/* ================ Налаштування ================ */
	$text_num_page = ''; // Текст кількості сторінок. {current} заміниться поточною, а {last} останньою. Приклад: 'Сторінка {current} з {last}' = Сторінка 4 з 60
	$num_pages = 10; // скільки посилань показувати
	$stepLink = 10; // після навігації посилання з певним кроком (значення = число (який крок) або '', якщо потрібно показувати). Приклад: 1,2,3...10,20,30
	$ dotright_text = '…'; / / Проміжний текст "до".
	$dotright_text2 = '...'; / / Проміжний текст "після".
	$backtext = '<<<'; // Текст "перейти на попередню сторінку". Ставимо '', якщо це посилання не потрібне.
	$nexttext = '>>>'; // Текст "перейти на наступну сторінку". Ставимо '', якщо це посилання не потрібне.
	$first_page_text = '« остання'; // текст "першій сторінці" чи ставимо '', якщо замість тексту потрібно показати номер сторінки.
	$last_page_text = 'перша»; // текст "до останньої сторінки" або пишемо '', якщо замість тексту потрібно показати номер сторінки.
	/* ================ Кінець Налаштувань ================ */

	global $wp_query;
	$posts_per_page = (int) $wp_query->query_vars['posts_per_page'];
	$paged = (int) $wp_query->query_vars['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='';//виводимо навігацію
		$out.= $before."<div class='wp-pagenavi'>n";
				if ($text_num_page) {
					$text_num_page = preg_replace ('!{current}|{last}!','%s',$text_num_page);
					$out.= sprintf ("<span class='pages'>$text_num_page</span>",$paged,$max_page);
				}

				if ($backtext && $paged!=1) $out.= '<a href="'.get_pagenum_link(($paged-1)).'">'.$backtext.'</a>';

				if ($start_page >= 2 && $pages_to_show < $max_page) {
					$out.= '<a href="'.get_pagenum_link().'">'. ($first_page_text?$first_page_text:$max_page) .'</a>';
					if($dotright_text && $start_page!=2) $out.= '<span class="extend">'.$dotright_text.'</span>';
				}

				for($i = $start_page; $i <= $end_page; $i++) {
					if($i == $paged) {
						$out.= '<span class="current">'.($max_page-$i+1).'</span>';
					} else {

						$out.= '<a href="'.get_pagenum_link($i).'">'.($max_page-$i+1).'</a>';
					}
				}

				//Посилання з кроком
				if ($stepLink && $end_page < $max_page){
					for($i=$end_page+1; $i<=$max_page; $i++) {
						if($i % $stepLink == 0 && $i!==$num_pages) {
							if (++$dd == 1) $out.= '<span class="extend">'.$dotright_text2.'</span>';
							$out.= '<a href="'.get_pagenum_link($i).'">'.($max_page-$i+1).'</a>';
						}
					}
				}

				if ($end_page < $max_page) {
					if($dotright_text && $end_page!=($max_page-1)) $out.= '<span class="extend">'.$dotright_text2.'</span>';
					$out.= '<a href="'.get_pagenum_link($max_page).'">'. ($last_page_text?$last_page_text:1) .'</a>';
				}

				if ($nexttext && $paged!=$end_page) $out.= '<a href="'.get_pagenum_link(($paged+1)).'">'.$nexttext.'</a>';

		$out.= "</div>".$after."n";
	if ($echo) echo $out;
	else return $out;
}

Залишити коментар

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