Функция next_posts_link() работает только с оригинальным $wp_query
У меня есть пользовательский шаблон, в котором я хочу отображать постраничную навигацию для записей блога. Вот начало моего файла:
$wp_query = new WP_Query($args);
if($wp_query->have_posts()){
while($wp_query->have_posts()){ $wp_query->the_post();
// какой-то код...
<?php next_posts_link('Старые записи'); ?>
<?php previous_posts_link('Новые записи'); ?>
Это работает нормально - отображаются ссылки "СТАРЫЕ" и "НОВЫЕ" записи, когда это необходимо. На первой странице отображается только ссылка на более старые записи. На второй странице - обе ссылки (на новые и еще более старые записи) и т.д.
Но я не хочу перезаписывать текущий $wp_query
... Я хочу использовать, скажем, $wp_query2
для этого цикла. И в этом случае ссылки вообще не появляются.
Согласно документации: http://codex.wordpress.org/Function_Reference/next_posts_link эти функции выводят ссылки на предыдущий/следующий набор записей в текущем запросе. Я предполагаю, что $wp_query2
не является моим "ТЕКУЩИМ ЗАПРОСОМ", а $wp_query
всегда им является. Можно ли это как-то изменить?
ОБНОВЛЕНИЕ:
Если вручную добавить &paged=2
к ссылке, то она корректно переходит на следующий набор записей (следующую страницу), и на второй, третьей и т.д. страницах previous_posts_link()
работает, даже если я использую $wp_query2
. Таким образом, мне не хватает только функциональности next_posts_link()
на каждой странице.
Функции next_posts_link
и previous_posts_link
используют глобальную переменную $wp_query
.
function get_next_posts_link( $label = null, $max_page = 0 ) { global $paged, $wp_query;
http://core.trac.wordpress.org/browser/tags/3.5/wp-includes/link-template.php#L1523
Это означает, что для их корректной работы необходимо сделать следующее:
$orig_query = $wp_query; // Сохраняем оригинальный запрос
$wp_query = new WP_Query($args); // Устанавливаем новый запрос
// остальной код
$wp_query = $orig_query; // Восстанавливаем оригинальный запрос
Если вы больше не используете $wp_query
в рамках этой загрузки страницы, нет необходимости сохранять его. Можно легко скопировать эти основные функции, модифицировать их для принятия параметра запроса и создать собственные функции пагинации.

Спасибо. Более тонкий подход, чем просто перезапись $wp_query. Функции *_post_link используют $wp_query только для вычисления значения параметра $max_pages, поэтому в обсуждении на Stack Overflow предлагают просто передавать это значение вместо перезаписи $wp_query. Что в каком-то смысле кажется проще, но вызывает у меня легкое беспокойство, так как предполагает, что будущие версии WP будут вести себя так же (нет гарантии: это не часть API/контракта, а скорее знание внутренней работы кода с переменными). http://stackoverflow.com/questions/14364488/wordpress-pagination-next-posts-link-on-custom-wp-query-not-showing

Это справедливое замечание, но вы же возвращаете переменную обратно, поэтому перезапись $wp_query
не должна быть проблемой. Честно говоря, я редко сталкиваюсь с этой проблемой — pre_get_posts
делает её решение довольно простым.

Извините, я был неясен. Я согласен, ваш метод безопасен. Моё замечание о рискованности относилось к решению на Stack Overflow. То решение выглядит проще на первый взгляд (просто добавить параметр), но оно основано на предположениях о внутренней работе кода WordPress... скорее всего безопасно, но внутренняя реализация может измениться. +1 вашему решению, так как оно кажется более устойчивым к изменениям в будущем.

Изучая исходный код WordPress, можно заметить, что next_posts_link использует глобальную переменную $paged. Похоже, это работает только для основного цикла.
Довольно хорошее решение для реализации пагинации в дополнительных циклах можно найти здесь: http://weblogtoolscollection.com/archives/2008/04/19/paging-and-custom-wordpress-loops/
Оно включает явное указание параметра запроса paged, например так:
<h3>Последние статьи</h3>
<ul>
<?php
$temp = $wp_query;
$wp_query= null;
$wp_query = new WP_Query();
$wp_query->query('showposts=5'.'&paged='.$paged);
?>
Надеюсь, это поможет.

Я столкнулся с такой же проблемой. У меня есть вложенные циклы, поэтому во внутреннем цикле я использую $wp_query = new WP_Query($args);
вместо глобального WP_Query
. Решение, которое я применил, заключалось в явной передаче параметра max_num_pages
в функцию next_posts_link
. Это также упоминалось в комментариях Andy Giesler.
Решение:
<?php
//внешний цикл
//некоторый внешний код
//начинается внутренний цикл
$inner_query = new WP_Query(
array('posts_per_page' => '4', 'paged' => get_query_var('paged'))
);
// ...код для отображения всех записей и т.д.
previous_posts_link( 'Старые записи' );
next_posts_link( 'Новые записи', $inner_query->max_num_pages ); //Обратите внимание на это
//заканчивается внутренний цикл
//другой внешний код
//заканчивается внешний цикл
?>
Причина, по которой мы должны это делать, заключается в том, что WordPress внутренне использует свойство $max_page
глобального WP_query, которое, если не определено, по умолчанию будет равно $max_page = 0
