WordPress Previous and Next Button Exclude Multiple Categories

I have a WordPress blog where posts have multiple categories selected. I am using a “Previous Post” and “Next Post” button at the bottom of each post. I would like the next or previous post to be in the same category– wordpress allows for this paramater in the next_post_link and previous_post_link functions, however it gets complicated when you have more than one category– it chooses the category with the lowest category ID, which leads to inconsistent post navigation.

What I want to do is get the post category from the permalink, which is formatted as /%category%/%postname% then get an array of all categories, remove the current post category from that array, then exclude that array from the next and previous post link, effectively leaving only the current category (as dictated by the permalink). For example, if the permalink is “myurl.com/music/september-guitar-post”, I want to exclude all categories except music from the previous and next post links.

Read More

Here is the code I’m using (that doesn’t seem to be functioning how I want it to):

function remove_item_by_value($array, $val = '', $preserve_keys = true) {
    if (empty($array) || !is_array($array)) return false;
    if (!in_array($val, $array)) return $array;

    foreach($array as $key => $value) {
        if ($value == $val) unset($array[$key]);
    }

    return ($preserve_keys === true) ? $array : array_values($array);
}

$link = get_permalink();
$link = explode('/',$link);
$currentCat = $link[3];
$currentCat = get_category_by_slug( $currentCat );
$currentCatId = $currentCat->term_id;
$categories = get_categories();
foreach($categories as $category) {
    $catList[] = $category->term_id;
}

$exclude = remove_item_by_value($catList, $currentCatId);
$exclude = implode(' and ',$exclude);

previous_post_link('%link', '« Previous post', TRUE, $exclude);
next_post_link('%link', '« Previous post', TRUE, $exclude);

All the code works until trying to use the $exclude string as a parameter in the next/prev post link functions. Upon further testing, simply trying to exclude a single category does not seem to work (next_post_link('%link', '« Previous post', TRUE, '3') ) for example. Can anyone confirm that this code actually functions as the documentation says it does?

How do I make this work?

Thanks!

Related posts

Leave a Reply

3 comments

  1. Note all four places where you input your categories to be excluded.
    the example id’s are id=10 id=20 id=30

    //Exclude Categories From Previous/Next
    function custom_prev_next_posts() { 
    global $thesis_design; 
    
    if (is_single() && $thesis_design->display['posts']['nav']) { 
        $previous = get_previous_post(FALSE,'10,20,30'); 
        $next = get_next_post(FALSE,'10,20,30'); 
        $previous_text = apply_filters('thesis_previous_post', __('Previous entry: ',  'thesis')); #filter 
        $next_text = apply_filters('thesis_next_post', __('Next entry: ', 'thesis'));   #filter 
    
        if ($previous || $next) { 
            echo "ttttt<div class="prev_next post_nav">n"; 
    
            if ($previous) { 
                if ($previous && $next) 
                    $add_class = ' class="previous"'; 
    
                echo "tttttt<p$add_class>$previous_text"; 
                previous_post_link('%link', '%title',FALSE,'10,20,30'); 
                echo "</p>n"; 
            } 
    
            if ($next) { 
                echo "tttttt<p>$next_text"; 
                next_post_link('%link', '%title',FALSE,'10,20,30'); 
                echo "</p>n"; 
            } 
    
            echo "ttttt</div>n"; 
        } 
      } 
    } 
    
    add_action('wp_hook_after_content', 'custom_prev_next_posts'); 
    remove_action('wp_hook_after_content', 'wp_prev_next_posts');  
    
  2. According to next_page_linkDocs, you need to pass the excluded categories as a string containing the ids separated by " and ":

    $exclude = implode(' and ', $exclude);
    next_post_link('%link', '&laquo; Previous post', TRUE, $exclude);
    previous_post_link('%link', '&laquo; Previous post', TRUE, $exclude);
    

    If the documentation is not lying, this should work.