Next and previous post link in same custom taxonomy

Until now, if you use next_post_link(‘%link’, ‘%title’, true) or previous_post_link(‘%link’, ‘%title’, true) to get the adjacent post for a custom post type which has a taxonomy assigned to it, it doesn’t work as intended. This is because these two functions are based on get_adjacent_post() which is hardcoded to look to the taxonomy ‘category’. So hard luck if you need them to work for your custom taxonomy.

There is a plugin that helps solve this issue: http://wordpress.org/extend/plugins/previous-and-next-post-in-same-taxonomy (update: this plugin is no longer available).  And work is ongoing to resolve this, which you might want to have a read: http://core.trac.wordpress.org/ticket/17807 .

However, if you have customised the order of your custom post type posts, the above plugin is not going to work, because the above mentioned functions are hardcoded to get next and previous posts based on their post dates.

So if you need to get next and previous post links in the same custom taxonomy, with a custom posts order, you might want to try these few lines of codes in your single.php template:

// get_posts in same custom taxonomy
$postlist_args = array(
   'posts_per_page'  => -1,
   'orderby'         => 'menu_order title',
   'order'           => 'ASC',
   'post_type'       => 'your_custom_post_type',
   'your_custom_taxonomy' => 'your_custom_taxonomy_term'
); 
$postlist = get_posts( $postlist_args );

// get ids of posts retrieved from get_posts
$ids = array();
foreach ($postlist as $thepost) {
   $ids[] = $thepost->ID;
}

// get and echo previous and next post in the same taxonomy        
$thisindex = array_search($post->ID, $ids);
$previd = $ids[$thisindex-1];
$nextid = $ids[$thisindex+1];
if ( !empty($previd) ) {
   echo '<a rel="prev" href="' . get_permalink($previd). '">previous</a>';
}
if ( !empty($nextid) ) {
   echo '<a rel="next" href="' . get_permalink($nextid). '">next</a>';
}

Hope this helps!

Update:

The above issues to get adjacent posts based on taxonomy has been fixed according to http://core.trac.wordpress.org/ticket/17807 , but this is still limited to getting posts sorted by post date only. However, this is being resolved here: https://core.trac.wordpress.org/ticket/26937 .

You can now add a $taxonomy argument to each of the adjacent post functions. Previously, related functions took an array of category (IDs) to search. These can now be taxonomy term IDs and each function now has $taxonomy = ‘category’ as an optional argument.

Related functions affected: get_previous_post(), get_next_post(), get_adjacent_post(), get_adjacent_post_rel_link(), adjacent_posts_rel_link(), next_post_rel_link(), prev_post_rel_link(), get_boundary_post(), get_previous_post_link(), previous_post_link(), get_next_post_link(), next_post_link(), get_adjacent_post_link(), adjacent_post_link().

24 Comments

  1. Hello from 2018. Your code is still working like a charm. I do have one problem that a customer wants. I am cycling through pieces of artwork, which is my CPT. The customer wants to be able to cycle through posts no matter what the index. For example, if there are 10 art pieces, and we start at the first, click ‘next’, and go to the 2nd. When we get to the 10th (end of array) she wants to be able to click ‘next’ again and go to art piece #1 (start over). Any suggestions on how to do that using your piece of code, which works great? Thank you for any help

    • Kevin

      December 10, 2018 at 12:18 pm

      Just something quick off my mind. Since the first post in the ‘series’ will be referenced by $ids[0], you might want to do something like this:

      if ( !empty($nextid) ) {
         echo '<a href="' . get_permalink($nextid). '" rel="next">next</a>';
      } else {
         $nextid = $ids[0];
         echo '<a href="' . get_permalink($nextid). '" rel="next">next</a>';
      }

      Let me know if this helps?

      • Hey Kevin, first off thank you so much for your work, and getting back to me quickly, especially since you wrote this code so long ago and it is still working great. Before you replied, I found a solution that I wanted to share with you. This will allow you to click ‘Next’ or ‘Previous’ when the array index is 0 (empty) and start the loop over again, basically making an infinite loop of posts. If you like it, please take it and share with your readers, a small token of my appreciation.

        I used an ELSE statement and the PHP function end() to make a new variable that pointed to the end of the $ids array. Basically I made an else statement, added $previous = end($ids); and put get_permalink($previous); to restart the index of post ids.

        • Kevin

          December 10, 2018 at 6:41 pm

          Hey Esteban, thanks for sharing and explaining what you did. Instead of end(), you might want to try using $previous = $ids[count($ids)-1] to prevent the actual internal pointer of the array from moving. And yes, in my previous reply to you, I had not considered the case where the user is viewing the first post in the series and accesses the last post by clicking the ‘previous’ link.

          The full solution would be something like this:

          // get and echo previous and next post in the same taxonomy
          // only show previous and next links if there are more than 1 post in the series        
          if ( count($ids) > 1) { 
             $thisindex = array_search($post->ID, $ids);
          
             if ( $thisindex == 0 ) {
                // user is viewing first post, and we retrieve last post when user clicks previous
                $previd = $ids[count($ids)-1];
             } else {
                $previd = $ids[$thisindex-1];
             }
             if ( $thisindex == count($ids)-1 ) {
                // user is viewing last post, and we retrieve first post when user clicks next
                $nextid = $ids[0];
             } else {
                $nextid = $ids[$thisindex+1];
             }
          
             echo '<a rel="prev" href="' . get_permalink($previd). '">previous</a>';
             echo '<a rel="next" href="' . get_permalink($nextid). '">next</a>';
          }
  2. Hola!

    Muchas Gracias, ha sido de mucha ayuda tu post!

    Feliz Día!

  3. After what seemed like way too much searching I found this which helped me greatly. Thank you.

  4. Hi, great trick, but I have a “Notice Message” if you a WP_Debug enabled.

    On the first and last post about the custom post taxonomy I have this:

    Example I have a 4 post with the same taxonomy and I have this result:

    – 1 Custom Post Type – Notice: Undefined offset: -1
    – 2 Custom Post Type – Nothing Happend
    – 3 Custom Post Type – Nothing Happend
    – 4 Custom Post Type – Notice: Undefined offset: 4

    The problem about this notice is this two variables:

    $previd = $ids[$thisindex-1];
    $nextid = $ids[$thisindex+1];

    How to resolve?

    Thanks.

    • Hi Alessio, offhand this is what I can think of. Let me know if it works?

      // get and echo previous and next post in the same taxonomy
      $thisindex = array_search($post->ID, $ids);
      if ( $thisindex != 0 ) {
         $previd = $ids[$thisindex-1];
         echo '<a rel="prev" href="' . get_permalink($previd). '">previous</a>';
      }
      if ( $thisindex != count($ids)-1 ) {
         $nextid = $ids[$thisindex+1];
         echo '<a rel="next" href="' . get_permalink($nextid). '">next</a>';
      }

      • Hi Kevin

        I couldn’t get this to work either and my custom post navigation seems to break at the same point as Alessio, ie the $previd and $nextid variables. I’ve checked the array of $ids, and its definitely the correct set of single custom posts with the matching custom taxonomy that I want to target, but I cant get the prev and next links to work through this array.

        It will work with a ‘next’ link for the first post in the array, but when I then click ‘next’ to navigate to post 2 in the array, the ‘next’ link is still pointing to this same post, post 2, and doesn’t echo the ‘prev’ link either.

        Would really appreciate your thoughts on this…

        • Hi Nathalie, how many posts do you currently have for the particular taxonomy? Your case could be different from Alessio’s. I believe Alessio has got it working, just that when he’s viewing the first post, $previd returns undefined, and at the last post, $nextid returns undefined, which I’ve tried to resolve in my reply to him.

          • Hi Kevin, the number of posts will vary because the custom taxonomy is part of a custom events section with 4 custom taxonomy types ( ‘event types’ set to work as per ‘categories’). One of them currently has two posts, another has 4. At the moment I gave up and removed it as the site is about to be launched. I could stick it back in and provide the code later today to show you what I’m doing?

      • That piece of code, fixed the problem with the first and last post getting a notice. You saved my day! Thank you.

  5. Oh man! You are a hero!
    Thanks for that.

    I even needed posts in several (two) custom taxonomies.
    So I adapted your code a little bit.
    Sharing is caring, so:

    $first = wp_get_post_terms( $post->ID, ‘first_taxonomy_name’ );
    $first_slug = $first[0]->slug;

    $second = wp_get_post_terms( $post->ID, ‘second_taxonomy_name’ );
    $second_slug = $second[0]->slug;

    $args = array(
    ‘post_type’ => ‘tour’,
    ‘tax_query’ => array(
    ‘relation’ => ‘AND’,
    array(
    ‘taxonomy’ => ‘first_taxonomy_name’,
    ‘field’ => ‘slug’,
    ‘terms’ => $first_slug
    ),
    array(
    ‘taxonomy’ => ‘second_taxonomy’,
    ‘field’ => ‘slug’,
    ‘terms’ => $second_slug
    )
    )
    );
    // The Query
    $the_query = new WP_Query( $args );

    // get ids of posts retrieved from get_posts
    $ids = array();

    // The Loop
    if ( $the_query->have_posts() ) {
    while ( $the_query->have_posts() ) {
    $the_query->the_post();
    $ids[] = get_the_id();
    }
    } else {
    // no posts found
    }
    /* Restore original Post Data */
    wp_reset_postdata();

    // print_r($ids);

    // get and echo previous and next post in the same taxonomy
    $thisindex = array_search($post->ID, $ids);
    $previd = $ids[$thisindex-1];
    $nextid = $ids[$thisindex+1];
    if ( !empty($previd) ) {
    echo ‘previous‘;
    }
    if ( !empty($nextid) ) {
    echo ‘next‘;
    }

    I hope that helps someone as well.

  6. Clear code. Easy to understand and a great explanation, thanks a lot!

  7. Thank you so much man! Totally solves my problem. Clean code and get_posts() thumbs up.

  8. Dude you are gifted.

    Thanks a lot for the smart, simple and perfect working snipplet :D

  9. Dammit dude. One beer for you. This is what i was looking for over 2 hours. This works !

    Have a nice night.

  10. Thank you so much for this post. I have looked hard and found lots of methods and plugins for this, but your solution worked great with very little footprint. Great job!

  11. Great post! It worked perfect also for me.

    I was wondering if you could explain how to show a numebred list (1,2,3,4,5,6…) instead of next and prev links.

    Thank you very much.

    • Hi Berta, I suppose that you are trying to page links for a custom taxonomy archive? If that is the case, maybe you’ll want to look into using the function paginate_links.

      But if you are trying to do this in a singular post, and show for example the previous 3 posts and the next 3 posts links in a numbered list, you could try the following. Offhand, I’m thinking you could try this concept:

      // get and echo previous 3 post and next 3 post links in the same taxonomy
      $thisindex = array_search($post->ID, $ids);
      for ($i = $thisindex-3; $i <= $thisindex+3; $i++) {
      $thisid=$ids[$i];
      if ( !empty($thisid) ) {
      echo '<a href="' . get_permalink($thisid). '" rel="nofollow">' . $i . '</a> ';
      }
      }

      Haven’t tested this though, so let me know if it works?

  12. This works great, thanks for sharing.
    Anyway to dynamically pull the current taxonomy into the code?

    For example, if I have a taxonomy called cities and it has 20 or so listed within that taxonomy.

    How could I call Portland or Seattle dynamically into the taxonomy field within that code depending on what page they are currently on?

    I hope this makes sense.
    Any help you could provide would be very helpful.
    Thanks in advanced.

    Steve

    • Hi Steve, need to understand more specifically what you are trying to do. I assume you’ve got a taxonomy named ‘cities’, and you’ve got 20 taxonomy terms (eg, Portland, Sealtle and so on) listed under it, yea? You didn’t state the context of your use case, so I’m gonna just generaly point you in the following direction: So let’s say you are on a certain post (ie a singular post template), you’ll need to dynamically get 2 sets of data, one is the posttype of this post, and the 2nd would be the taxonomy and terms the post is assigned to.

      To get the post type, you’ll need to call:
      $posttype = get_query_var(post_type);

      To get the taxonomies of the posttype, you’ll need to call:
      $taxonomies=get_taxonomies(
      array(
      object_type => array ($posttype)
      ),
      'names'
      );
      foreach ($taxonomies as $taxonomy ) { //Assigning all tax names of the posttype to an array
      $taxnames[] = $taxonomy;
      }

      And assuming you have only 1 taxonomy for your post type, call this to get the tax terms assigned to current post:
      $terms = get_the_terms( $post->ID, $taxnames[0] );
      foreach ( $terms as $term ) { //Assigning tax terms of current post to an array
      $taxterms[] = $term->name;
      }

      Then using the above data in your query:
      $postlist_args = array(
      'posts_per_page' => -1,
      'orderby' => 'menu_order title',
      'order' => 'ASC',
      'post_type' => $posttype,
      'tax_query' => array(
      array(
      'taxonomy' => $taxnames[0],
      'field' => 'name',
      'terms' => $taxterms
      )
      )
      );
      $postlist = get_posts( $postlist_args );

  13. This is what I was looking for. Worked like a charm. I ended up not using the custom taxonomy.

    Here used on the post_type portfolio http://rxbalance.org/portfolio/weighing-in-on-the-evidence/

Leave a Reply to Berta Cancel reply

Your email address will not be published.

*

© 2019 Bucket Press

Top