One of the nicest things about using WP_Query is that it allows you to completely customize the data that you’re bringing back to the front end.

For those of you who are completely unfamiliar with this API, it’s a powerful class that allows you to custom tailor a query against the WordPress database for retrieving information about posts, pages, custom post types, and so on.

If you’re using one of the more common features of WordPress, such as those mentioned above, then it’s relatively easy to get started; however, if you’re doing more complicated work, such as including multiple custom queries in a single view, then there are some challenges that you may discover.

Personally, I’ve been working on a project where I have two custom queries running in a template and I needed to paginate the results. The problem is that using the usual functions for doing this, that is:

Were not working as expected.

Ultimately, it required me passing a little bit more information to the query’s arguments array and to the pagination link functions. Here’s how you can setup WP_Query Pagination to work properly in custom queries.

A Few Assumptions

There are two assumptions that I’m making about your setup:

  1. You’re using pretty permalinks. That is, your permalink structure includes something like /%postname%/.
  2. You’re familiar with get_query_var specifically or pagination.

Assuming that you’re familiar with both of these, you should be good to go from defining your custom queries and for getting pagination to work correctly without any custom helper functions and by using the native WordPress API.

A Working Example

Defining The Query

Let’s assume that we’re just going to be pulling back a set of records for a custom post type called goals. First, we need to define the arguments for the query.

Personally, I think that defining the arguments in an array and then passing the array to the WP_Query class makes for more readable, manageable code, but that’s completely subjective.

// First, get a reference to the current author of the posts in this listing
$current_author = ( isset($_GET['author_name'] ) ) ? get_user_by( 'slug', $author_name ) : get_userdata( intval( $author ) );

// Next, define a way to get the current offset
function example_get_offset() {

	$number = 10;
	$page = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1

	return 1 == $page ? ( $page - 1 ) : ( ( $page - 1 ) * $number );

} // end example_get_offset

// After that, set the arguments for the query
$args = array(
	'post_type'	        =>	array( 'goal' ),
	'orderby'	          =>	'date',
	'order'		          =>	'desc',
	'posts_per_page'    =>	10,
	'offset'            => example_get_offset(),
	'paged'		          =>	get_query_var( 'page' ) ? get_query_var( 'page' ) : 1,
	'author'	          =>	$current_author->ID

// Finally, instantiate the query
$query = new WP_Query( $args );

The code comments should be relatively clear; however, there are two main arguments in the $args array that are worth noting:

  1. posts_per_page. This is somewhat of an arbitrary value, but this simply tells WordPress how many posts you want to pull back for a given page.
  2. paged. This parameter is what will give the pagination API functions their power. Above, we’re looking to see if the query variable exists. If so, we’ll use that value; otherwise, we’ll initialize it to one. The sublte nuance here is that the key is paged but the get_query_var parameter is page. Don’t miss that.

Finally, you may note that we’re pulling back all of those posts for the current author.

Setting The Pagination Links

Next, it’s time to setup the pagination links. For standard queries, we’re typically used to seeing something like this:

<div id="pagination">
	<ul class="pagination">
		<li id="previous-stories" class="arrow">
			<?php previous_posts_link(); ?>
		<li id="next-stories" class="arrow">
			<?php next_posts_link(); ?>
</div><!-- /#pagination -->

But that won’t actually work because of the custom query that we’ve defined above. Here’s what you need to do to take advantage of a custom setup with WP_Query Paging.

Using WP_Query Paging with Custom Queries

Notice that the API for both the next_posts_link and previous_posts_link functions accept two parameters:

    1. The label for the link
    2. The maximum number of pages that will be displayed

As such, here’s one way you’d define the markup provided above:

<div id="pagination">
	<ul class="pagination">
		<li id="previous-stories" class="arrow">
			<?php previous_posts_link( '<< Previous Stories', $query->max_num_pages ); ?>
		<li id="next-stories" class="arrow">
			<?php next_posts_link( 'Next Stories >>', $query->max_num_pages ); ?>
</div><!-- /#pagination -->

This way, you’re telling WordPress the maximum number of pages that are being retrieved based on the results of the custom query that has been executed.

By doing this, you should have no problem setting up WP_Query Paging in your work.