(This is a WordPress-specific tech note.)
After creating a separate loop on a fullpage template for custom posts, I found it was not properly paginating after the maximum posts per page had been reached.
A quick search on Google or Bing should have returned this immediately. Instead it took a great deal of hunting through the WordPress Codex, and several helpful blogs, so I wrote it up here to make sure it’s findable.
$wp-query: If you try to search for “$wp_query vs WP_query” or “$wp_query pagination” you get many useless results, and only by digging through them would you discover that the php variable $wp_query is a global object. (Something that significant ought to turn up sooner in search results.)
So if you decide to use a different variable as the result of a call to the function WP_query() (or as is more likely, you copy code from an example and it uses a different variable), the pagination functions do not work. They evidently rely on $wp_query as the active object to use in pagination.
So whether you use get_previous_posts_link() or previous_posts_link() or the similar ones for “next,” you must have an instance of $wp_query containing the result of your call to WP_query().
To see what I mean, consider the following snippet involving custom posts:
<?php /** Query Arguments */ ?> <?php $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; ?> <?php $args = array('posts_per_page' => 8, 'post_type' => 'my_custom_post_type', 'paged' => $paged ); ?> <?php /** Hold $wp_query */ ?> <?php $temp_wp_query = $wp_query; ?> <?php $loop = null; ?> <?php /** Custom $wp_query */ ?> <?php $loop = new WP_Query( $args ); ?> <ul> <?php while ( $loop->have_posts() ) : $loop->the_post(); ?> <li><h3><?php the_title(); ?></h3> <div class="entry-content"> <?php the_content(); ?> </div></li> <?php endwhile; ?> <?php /** Loop Pagination */ ?> <div id="loop-nav-next-prev"> <div class="loop-nav-previous"> <?php previous_posts_link( '← Newer Posts' ); ?> </div> <div class="loop-nav-next"> <?php next_posts_link( 'Older Posts →' ); ?> </div> </div> <?php /** Restore Post Data */ ?> <?php wp_reset_postdata(); ?> <?php /** Restore value of $wp_query */ ?> <?php $wp_query = null; ?> <?php $wp_query = $temp_wp_query; ?> </ul>
Apologies for all the inline php… that’s the code I was working with. Anyway, there’s only one thing preventing this code from working correctly:
The WP_query() result is assigned to the variable $loop.
So looping thru posts works up to the number of posts_per_page as you would expect, but the calls to previous_posts_link() and next_posts_link() return nothing.
If you instead use $wp_query as the variable assigned by WP_query(), you’ll get the usual expected results for pagination.