0

I want to display a list of categories excluding the category of the current single post that the user is navigating on. The list is displayed on the single.php template.

I'm using this code to display all categories and is working well but I can't find a way to exclude the current post category:

<ul class="submenu-category">
  <?php
    // your taxonomy name
    $tax = 'category';

    // get the terms of taxonomy
    $terms = get_terms( $tax, $args = array(
      'hide_empty' => false, // do not hide empty terms
    ));

    // loop through all terms
    foreach( $terms as $term ) {

        // Get the term link
        $term_link = get_term_link( $term );

        if( $term->count > 0 )
          // display link to term archive
          // echo '<a href="' . esc_url( $term_link ) . '">' . $term->name .'</a>';
          echo '<li><a data-filter=".'. $term->slug .'" href="javascript:void(0)" >' . $term->name .'</a></li>';

        elseif( $term->count !== 0 )
          // display name
          echo '' . $term->name .'';
    } ?>
</ul>

Any idea on how to achieve it?

1

The idea here would be to use the queried object's ID to get the post terms (because we are most probably outside the loop here, if inside the loop, just use get_the_ID()). From there, we can use wp_list_pluck() to get all the term ID's and simply pass that to get_terms() exclude parameter

Just a note, as from WordPress V4.5, the taxonomy should be passed as an arguments of $args, I'll handle both cases

PRE 4.5

// Set all our variables
$taxonomy = 'category';
$post_id  = $GLOBALS['wp_the_query']->get_queried_object_id();
$args     = [
    'hide_empty' => false
];

// Get the ID's from the post terms
$post_terms = get_the_terms( $post_id, $taxonomy );
if (    $post_terms
     && !is_wp_error( $post_terms )
) {
    $term_ids = wp_list_pluck( $post_terms, 'term_id' );

    // Get all the terms with the post terms excluded
    $args['exclude'] = $term_ids;
}

$terms = get_terms( $taxonomy, $args );

V 4.5 + version

// Set all our variables
$taxonomy = 'category';
$post_id  = $GLOBALS['wp_the_query']->get_queried_object_id();
$args     = [
    'taxonomy'   => $taxonomy,
    'hide_empty' => false
];

// Get the ID's from the post terms
$post_terms = get_the_terms( $post_id, $taxonomy );
if (    $post_terms
     && !is_wp_error( $post_terms )
) {
    $term_ids = wp_list_pluck( $post_terms, 'term_id' );

    // Get all the terms with the post terms excluded
    $args['exclude'] = $term_ids;
}

$terms = get_terms( $args );
  • 1
    This is an excellent explanation. It did the job, thanks! – wpuser May 13 '16 at 11:05
0

First you will need an array that contains all categories of the current post:

$current_cats = wp_get_post_categories(); // assuming you are in the loop

Then you have to loop through $current_cats and remove the items from $terms

    foreach( $current_cats as $cat ) {
        if (($key = array_search($cat, $terms)) !== false) {
            unset($terms[$key]);
            }
        }

Hopefully that works.

  • You can do this much faster. Note, you do not want to use wp_get_post_categories() as it makes an extra db call – Pieter Goosen May 13 '16 at 9:46
  • You mean explode get_the_category_list (', ') and then strip the tags, or something else? – cjbj May 13 '16 at 9:50
  • See my answer, I explained it there – Pieter Goosen May 13 '16 at 10:05
  • Sorry, i just clicked the link to your comment and didn't see you had added an answer. Yours is definitely smarter, but less easy to understand for beginning WP programmers, I think. – cjbj May 13 '16 at 10:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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