9

I've got custom template that I want to display paged blog posts. This is the beginning of my file:

$wp_query = new WP_Query($args); if($wp_query->have_posts()){ while($wp_query->have_posts()){ $wp_query->the_post(); //something... <?php next_posts_link('Older Entries'); ?> <?php previous_posts_link('Newer Entries'); ?> 

It works fine - it displays OLDER and NEWER links when it should. On the first page it will display only a link to older entires. On the second page both to newer entries and yet older ones etc.

But I don't want to overwrite current $wp_query... I want to use let's say $wp_query2 for this loop. And the links don't appear at all if I do this.

According to this: http://codex.wordpress.org/Function_Reference/next_posts_link they print a link to the prev/next set of posts within the current query. I assume that $wp_query2 isn't my "CURRENT QUERY" but $wp_query always is. Can I change that somehow?

UPDATE: Adding &paged=2 manually to the link causes it to correctly go to the next set of posts (next page) and on second, third etc. page previous_posts_link() works even if I use $wp_query2. So, I'm just missing next_posts_link() functionality on every page.

3 Answers 3

12

next_posts_link and previous_posts_link use the global $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

That means you need to do something like this to get those to work correctly.

$orig_query = $wp_query; $wp_query = new WP_Query($args); // the rest of your code $wp_query = $orig_query; 

If you are done with $wp_query for that page load there is no reason to preserve it. It should be pretty easy to copy those core functions, modify them to accept a query parameter and create your own paging functions.

3
  • 1
    Thanks. Subtler than just overwriting $wp_query. The *_post_link functions only use $wp_query to compute the $max_pages parameter value, so a Stack Overflow discussion recommends simply passing in that value rather than overwriting $wp_query. Which seems simpler in a way, but makes me a little nervous since it assumes future WP versions will act that way (not guaranteed: it's not part of the API/contract, but instead relies on knowledge of the code's inner variable handling). stackoverflow.com/questions/14364488/… Commented May 16, 2013 at 15:27
  • That is a good point but you are putting the variable back so overwriting $wp_query shouldn't be a problem. Honestly, I rarely even encounter this problem-- pre_get_posts makes it pretty easy to avoid. Commented May 16, 2013 at 15:33
  • Sorry, I was unclear. I agree, your method is safe. My comment about riskiness referred to the Stack Overflow solution. That other solution looks simpler on the surface (just add a parameter), but it relies on assumptions about the inner workings of WordPress core code... most likely safe, but inner code workings can change. +1 your solution because it seems more future-proof. Commented May 16, 2013 at 19:54
3

Looking at the wordpress source, it looks like next_posts_link uses the global var $paged. My guess is that is only going to work for the primary loop.

A pretty good solution on how to make pagination work for secondary loops is here: http://weblogtoolscollection.com/archives/2008/04/19/paging-and-custom-wordpress-loops/

It involves setting the paged query var explicitly in the query, like this:

<h3>Recent Articles</h3> <ul> <?php $temp = $wp_query; $wp_query= null; $wp_query = new WP_Query(); $wp_query->query('showposts=5'.'&paged='.$paged); ?> 

Hope that helps.

1

I ran into the same issue. I have nested loops, so in the inner loop I am using $wp_query = new WP_Query($args); instead of the global WP_Query. The solution I used was to explicitely pass max_num_pages to the next_posts_link function. This has been mentioned in the comments by Andy Giesler as well.

Solution:

<?php //outer loop //some outer code //inner loop starts $inner_query = new WP_Query( array('posts_per_page' => '4', 'paged' => get_query_var('paged')) ); // ...show all posts etc code previous_posts_link( 'Older posts' ); next_posts_link( 'Newer posts', $inner_query->max_num_pages ); //Note this //inner loop finishes //some other outer loop code //outer loop finishes ?> 

The reason we have to do this is that wordpress internally use global WP_query's $max_page property, which if is undefined then the default will be $max_page = 0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.