I am trying to exclude some categories from a for-loop.

<?php $categories = get_categories(array('exclude' => 'apps, windows')); ?>

<?php foreach ($categories as $category) : ?>
    // the_loop
<?php endforeach; ?>

Even though no error is thrown, it doesn't work: all categories are used in the loop. How can I exclude some categories by slug?

I am working with multiple sites that have different cat IDs but the same slug, so I need to filter by slug rather than by cat ID.

For future readers: Pieter Goosen answered this question and another in into a merged answer here.

  • exclude takes a comma separated string of ascending category ID's Apr 22, 2015 at 13:21
  • @PieterGoosen I'm aware of that, but because I am working with multiple sites that have different cat IDs but the same slug, I need to filter by slug rather than by cat ID. Apr 22, 2015 at 13:31
  • If you don't get an answer, I will post one a bit later. Leaving work now, so give me about 2 hours :-) Apr 22, 2015 at 13:33

2 Answers 2


As I already stated, straight from the codex


(string) Excludes one or more categories from the list generated by wp_list_categories. This parameter takes a comma-separated list of categories by unique ID, in ascending order

As you have stated, you have to use the category slug. To make this possible and dynamic, I think the best will be to write your own wrapper function to achieve this. We are going to use get_terms() (which is used by get_categories() internally) to get our categories and get_term_by() to get the category ID so that we can pass that to get_terms()

Here is the function, I have commented it well for better understanding (Requires PHP 5.4+)

function exclude_term_by( $taxonomy = 'category', $args = [], $exclude = [] )
     * If there are no term slugs to exclude or if $exclude is not a valid array, return get_terms
    if ( empty( $exclude ) || !is_array( $exclude ) )
        return get_terms( $taxonomy, $args );

     * If we reach this point, then we have terms to exclude by slug
     * Simply continue the process. 
    foreach ( $exclude as $value ) {

             * Use get_term_by to get the term ID and add ID's to an array
            $term_objects = get_term_by( 'slug', $value, $taxonomy );
            $term_ids[] = (int) $term_objects->term_id;


     * Set up the exclude parameter with an array of ids from $term_ids
    $excluded_ids = [
        'exclude' => $term_ids

     * Merge the user passed arguments $args with the excluded terms $excluded_ids
     * If any value is passed to $args['exclude'], it will be ignored
    $merged_arguments = array_merge( $args, $excluded_ids );

     * Lets pass everything to get_terms
    $terms = get_terms( $taxonomy, $merged_arguments ); 

     * Return the results from get_terms
    return $terms;

Before I go into usage, here are a few notes

  • The first parameter, $taxonomy is the particular taxonomy to pass to get_terms() inside the function, it defaults to category

  • The second parameter, $args takes the same parameters as get_terms(). Just a note, if the third parameter is set, the default exclude parameter's value is ignored if anything is passed to it. This value will be overridden by whatever is passed to $exclude. If nothing is passed to this parameter, and anything is passed to $exclude, you need to pass an empty array as value

  • The third parameter, $excludes takes an array of term slugs which should be excluded. If the value is not a valid array, get_terms() will be returned without excluding the necessary terms, so be sure to pass an array of slugs

  • Treat the output from the function in the same way you would with get_terms(). Remember, you should also check for empty values and WP_Error objects before using the value from the function

  • Modify and abuse the code as you see fit

Now for the usage in your template files. Note the empty array passed to the $args parameter if anything is passed to the $exclude parameter

$terms = exclude_term_by( 'category', [], ['term-slug-one', 'term-slug-two'] );
if ( !empty( $terms ) && !is_wp_error( $terms ) ) {
    ?><pre><?php var_dump($terms); ?></pre><?php

For any extra info on usage, see get_terms().


There's a small error on your first line of code. You should separate 'each' category with quotes in the array. So the first line should be:

<?php $categories = get_categories(array('exclude' => 'apps', 'windows')); ?>
  • Check my comment to OP. You should use ID's, not slug Apr 22, 2015 at 13:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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