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().

20 Comments

  1. Hola!

    Muchas Gracias, ha sido de mucha ayuda tu post!

    Feliz Día!

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

  3. 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). '" rel="nofollow">previous</a>';
      }
      if ( $thisindex != count($ids)-1 ) {
         $nextid = $ids[$thisindex+1];
         echo '<a rel="next" href="' . get_permalink($nextid). '" rel="nofollow">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.

  4. 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.

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

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

  7. Dude you are gifted.

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

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

    Have a nice night.

  9. 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!

  10. 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?

  11. 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 );

  12. 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

Your email address will not be published.

*

© 2017 Bucket Press

Top