Альтернатива плагіну 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
Додані посилання назад/вперед, приклад:
« ** на початок “назад… 11 12 13 14 15 16 17 18 … вперед» в кінець ** » Їх можна вимкнути (див. налаштування).- Прибрано баг такого типу:
1 … 2 3 4 5 6 7 8 … 50 або 1 … 21 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; }