I am showing the next post user should read as...

<?php previous_post_link('%link', '<span>%title</span>', TRUE); ?>

But, if there are 20 posts in a category and I am on the 7th one. Instead of showing the 8th one (above) I want to show the 1st (latest) one... as the next post. If I am on the first then it should show the 2nd as the next.

How can I do this ? Does previous_post_link have in build parameters to allow this.

  • No, there is no such built-in logic. What you will need to do, in my opinion, would be to establish some kind of post counter to determine the current positions of all posts in that particular category. You will then need do a check on this post counter/number, and if the current post is post 7 in queue, remove the post link and replace it with a manual link going back to post one Nov 25, 2014 at 6:40
  • Is it atleast possible to make it sort of cyclic. Like If there are 5 posts and I am on the 5th then since there is no 6th it should show next as 1st. @PieterGoosen Nov 25, 2014 at 6:48
  • That is possible, but again not natively. If my mind serves me correctly, this very topic of your comment has been handled before. Use the site search. :-) Nov 25, 2014 at 6:53
  • @PieterGoosen Tried searching... didn't find it. A little help...plz Nov 25, 2014 at 17:55
  • I have actually just completed a solution for this problem, your in luck. Will post soon :-) Nov 25, 2014 at 18:24

1 Answer 1


There is no way to do this natively, so you will need to do this by custom functions.

Here is what you will need to do:

(This complete solution is based on the build-in taxonomy, category)

  • You will need to implement a system whereby you will need to determine the current post position of the current post been viewed in the specific category.

  • You will need to get the ID of the latest post in the specific category, in other words, the latest published.

  • Link to the latest post in that category when you are viewing the 7th post and also the link to post 6.

  • Only show the link to post one on all posts older than the 7th post.

  • Display both the next_post_link() and previous_post_link() when viewing newer posts than the 7th post


We need to get the post ID of the single post being viewed, and also the post type if necessary. To get this, you can make use of get_queried_object()

Once we have that, we need to determine to which category the post belongs to. This is done by using get_the_category(). (Take note, this will only work successful when a post belongs to one category only. If there are more than one category, the first one is used).

All this info will be used in a custom query making use of get_posts. As we only need the post ID's, we are only going to retrieve that.

This returned array of post ID's is the data that will be used to determine post position and the newest post in that category.

This query can get quite expensive later, so we will save all our data into a transient which I have set to expire every 7 days. All the data needed will be stored in variable called $numbers

We also need to delete and recreate the transients once posts are updated, deleted or published. For this we will use the transition_post_status action hook

With this all set up, we move over to the single.php template. This is where you are going to display what is needed. as stated

  • Display only newest post link for posts older than 7

  • Display the newest post link and next_post_link() on post 7

  • Display both the next_post_link() and previous_post_link() when viewing newer posts than the 7th post

To get the newest post from the category, you will use get_post() with the ID saved in the $numbers variable

This should do it


(Modify as needed. I have tested it and it works according to what you stated in your question)

In functions.php

function get_display_post_number() {

    $query_object   = get_queried_object();
    $id             = $query_object->ID;
    $transient_id   = 'post_number_' . $id;

    if ( false === ( $numbers = get_transient( $transient_id ) ) ) {
        $categories = get_the_category( $id );
        $cat        = $categories[0]->cat_ID;

        $post_args = [ 
            'post_type'         => $query_object->post_type,
            'cat'               => $cat,
            'fields'            => 'ids',
            'posts_per_page'    => -1,
            'order'             => 'ASC',


        $q = get_posts( $post_args );

        $total_posts    = count( $q );
        $post_number    = array_search( $id, $q ) + 1;
        $current_post   = $total_posts - $post_number + 1;
        $newest_post    = $q[$total_posts - 1];

        $numbers = [
            'post_number'   => $post_number, 
            'newest_post'   => $newest_post, 
            'total_posts'   => $total_posts, 
            'current_post'  => $current_post 

        set_transient( $transient_id, $numbers, 7 * DAY_IN_SECONDS );

    return $numbers;

add_action( 'transition_post_status', function ( $new_status, $old_status, $post )

        global $wpdb;
        $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient%_post_number_%')" );
        $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient_timeout%_post_number_%')" );

}, 10, 3 );

In single.php

$a = get_display_post_number();
if( 7 === $a['current_post'] ) { 

    next_post_link('%link', '%title', TRUE);
    echo '</br>';

    $latest_post = get_post( $a['newest_post'] );
    $post_link = get_permalink( $latest_post->ID );

    echo '<a href="' . $post_link . '">' . $latest_post->post_title . '</a></br>';

}elseif( 7 < $a['current_post'] ) { 

    $latest_post = get_post( $a['newest_post'] );
    $post_link = get_permalink( $latest_post->ID );

    echo '<a href="' . $post_link . '">' . $latest_post->post_title . '</a></br>';


    next_post_link('%link', '%title', TRUE);
    echo '</br>';
    previous_post_link('%link', '%title', TRUE);

  • What is 7 here ? the $post->ID ?? Nov 26, 2014 at 5:35
  • Okay I understood.... Really Cool :) Nov 26, 2014 at 5:50
  • 1
    Did you get this solved? Would like hear how you solved it. If my solution work, please accept it. If you used your own solution, please post it as an answer and accept your own solution. Please help keep this site and your question constructive :-) Dec 13, 2014 at 14:09

Your Answer

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

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