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.
    – s_ha_dum
    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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.