When building templates for WordPress, you generally have pagination functions that come from the application itself.

WordPress Pagination: Get Next Post

These incude things like:

And there are a few other posts that give you greater granularity around taxonomies such as get_adjacent_post().

I recommend reading all of the above links because they are useful if you’re building a theme, working with custom post types, or are simply looking for a deeper understanding of some of the common template tags.

If, however, you’re looking for an easy way to write your WordPress pagination utility (which I’ll explain the rationale for momentarily), then the rest of this post will cover exactly that.

Custom WordPress Pagination

First, whenever you’re building a web application for someone, there are bound to be nuances in which native WordPress functionality may not work. Perhaps it doesn’t work as expected, it doesn’t work as intended, or it doesn’t serve your needs.

Whatever the case, that doesn’t mean pagination can’t be built to serve your purposes. After all, the core of pagination – especially as it relates to single post pagination – is basically this:

From the current post, see if a post exists prior to it and see if a post exists after it. If either type of post exists, then provide a link to it; otherwise, don’t.

From here, we can determine that we’ll need the following features:

  1. a way to determine if a post exists behind the current post,
  2. a way to determine if a post exists after the current post,
  3. a way to retrieve a given post,
  4. a way to get the permalink for the given post.

I work to be very particular in the language above, though, because a post that’s “behind” or “after” a given post may not have an ID that’s one-less-than-the-ID of the current post.

It’s simply the first post that’s published and can be retrieved in either direction, right?

So with that in mind, this means we’ll need two queries:

  • a query to retrieve the post behind the current post,
  • a query to retrieve the post after the current post.

For this example, I’m assuming that you have access to the current post’s ID through the get_the_ID() function.

Get a Post Behind The Current Post

To do this, we need to create a simple query that will grab one published post from the database of the specified post type, and that’s related to the position of the current post.

We can do this by limiting the result set to one, ordering the results in descending order, and comparing the value of the post ID:

This will return an array of results that we’ll see how to manage in just a bit.

Get the Post After The Current Post

For the next post, we write a similar query. But instead, we look for the next value that’s larger and that’s ahead of the current ID:

Now we need a few functions to determine if posts exists. We can do this with the results array that’s returned.

Check if a Post Exists

Note that in the following example, the function accepts the array of results and simply returns if there is a previous post. The results that are passed into this function should be from the previous post query above.

Secondly, note that it’s private. You may want to make yours public depending on how you want to construct your templates.

And then for the next post, it looks the same but remember the results that are being passed into this function are from a different query.

And finally, we can use these conditional functions to get the permalink.

Get the Link

Remember, the way in which you use this function may vary than the implementation I’ve provided. So if you don’t need it to be private, change its visibility and use it in your template as needed.

Finally, note this function accepts the results that you pass into it from either query and will retrieve the ID property from the first index of the results.

This is because the results are limited to one and its predicated on your use of the conditional functions. That is, you can do something like:

  • if there is a next post then get the next post link

But your implementation may vary.

Why is This Needed?

It may not be needed. That’s the whole thing: If you’re using WordPress out-of-the-box with very little customization or extension and don’t need to do anything beyond what it can provide, then you may not need this.

If, on the other hand, you’re looking for a way to introduce WordPress pagination functionality on a single post, then this is a way to do it that can properly handle the case of posts that are of a specific post type but don’t have sequential IDs (and that work only with a publish post status).