WordPress offers built-in functions to display the previous and next post link.
next_post_link( $format, $link, $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ); previous_post_link( $format, $link, $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' );
As you can see there’s a boolean parameter named ‘in_same_term’.
This allows you to :
Indicates whether previous post must be within the same taxonomy term as the current post. If set to 'true', only posts from the current taxonomy term will be displayed. If the post is in both the parent and subcategory, or more than one term, the previous post link will lead to the previous post in any of those terms.
More documentation for those functions here.
Very handy !
But there are some cases when you need to go a bit further into coding. Typically, if you don’t want to modify a parent theme and rather customize it from a child theme.
Let’s say you have a theme with a custom display for your post navigation links, like the one used in the Customizr theme :
<ul class="pager"> <?php if ( get_previous_post() != null ) : ?> <li class="previous"> <span class="nav-previous"> <?php $singular_nav_previous_text = apply_filters( 'tc_singular_nav_previous_text', _x( '←' , 'Previous post link' , 'customizr' ) ); previous_post_link( '%link' , '<span class="meta-nav">' . $singular_nav_previous_text . '</span> %title' ); ?> </span> </li> <?php endif; ?> <?php if ( get_next_post() != null ) : ?> <li class="next"> <span class="nav-next"> <?php $singular_nav_next_text = apply_filters( 'tc_singular_nav_next_text', _x( '→' , 'Next post link' , 'customizr' ) ); next_post_link( '%link' , '%title <span class="meta-nav">' . $singular_nav_next_text . '</span>' ); ?> </span> </li> <?php endif; ?> </ul>
In the above code, the in_same_term parameter is not set. To display the prev/next post link of the same category, we then have to filter the default behaviour or WordPress with the hooks API provided in wp-includes/link-template .
add_filter('tc_previous_single_post_link_args', 'navigate_in_same_taxonomy'); add_filter('tc_next_single_post_link_args', 'navigate_in_same_taxonomy'); function navigate_in_same_taxonomy( $args ){ $args['in_same_term'] = true; return $args; }
Add it to your child-theme functions.php.
Everything you need to know about creating a child theme with Customizr here.
Here’s the code that will allow you to restrict the post navigation to the same category :
(Paste it in your functions.php)
add_filter( 'get_next_post_join', 'navigate_in_same_taxonomy_join', 20); add_filter( 'get_previous_post_join', 'navigate_in_same_taxonomy_join', 20 ); function navigate_in_same_taxonomy_join() { global $wpdb; return " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id"; } add_filter( 'get_next_post_where' , 'navigate_in_same_taxonomy_where' ); add_filter( 'get_previous_post_where' , 'navigate_in_same_taxonomy_where' ); function navigate_in_same_taxonomy_where( $original ) { global $wpdb, $post; $where = ''; $taxonomy = 'category'; $op = ('get_previous_post_where' == current_filter()) ? '<' : '>'; $where = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy ); if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) ) return $original ; $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) ); $term_array = array_map( 'intval', $term_array ); if ( ! $term_array || is_wp_error( $term_array ) ) return $original ; $where = " AND tt.term_id IN (" . implode( ',', $term_array ) . ")"; return $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $where", $post->post_date, $post->post_type ); }
14 thoughts on “Restrict the post navigation to the same category”
there’s no “order by” clause anywhere.
I don’t suppose anyone would know how to amend the code to sort the results … say like “order by tr.post_name asc” ?
Hello Nicholas,
I installed the script and there was no PHP error either. Unfortunately no results are shown anymore, the whole block is not shown.
Where can I still search?
Kind regards
Gert
Hallo Nikolaus,
ich habe das script eingebaut und es gab auch keinen PHP-Fehler. Leider werden keine Ergebnisse mehr angezeigt, der ganze Block wird nicht angezeigt.
Wo kann ich noch suchen?
mfg
Gert
Hello Nicholas,
I installed the script and there was no PHP error either. Unfortunately no results are shown anymore, the whole block is not shown.
Where can I still search?
Kind regards
Gert
Hello Nicolas,
there was a current version for Hueman ProVersion: 1.3.0.
Kind regards
Device
it works very well. I just need to add a condition to run for custom post type. I will be glad if you help me.
Like this
Where should I add
if ( is_singular( ‘result’ ) ) {
This solution helped me. Thank you.
Nicely done man.
Many thanks Nicolas,
You solved a very frustrating problem for me. Worked perfectly.
HI, Thanks for this code!!!
Just used it and it works good!!
Hi Nicolas,
despite the lack of comments on this cool snippet, it is one of the most valuable/interesting option when it comes to posts navigation;
unfortunately it does not work with the latest versions of Customizr.
Due to the complexity of your snippet I can’t help debugging, but maybe if pointed on the right direction I can try to figure out a workaround 😉
Thanks,
G.
Works great! and I had problems before because some of the posts where sharing different categories.
Thanks so much.