Exclude all sub categories from wp_query

I’ve been searching high and low for and answer to this, but I’m not actually sure it’s possible!

I have a WP_Query that pulls posts from almost everything, however, I wish to exclude a specific category and/or all it’s sub categories.

Read More

Searching around people are yet to find a solution for this.

Here’s my query so far:

$args = array(
    'post_type' => 'sell_media_item',
    'cat' => -98,
    'orderby' => 'desc',
    'paged' => $paged,
    'posts_per_page' => 20
); ?>

<?php $loop = new WP_Query( $args ); ?>

I thought just excluding cat 98 would grab all the sub categories too, but apparently not.

I’ve tried using:

category__not_in, depth=0, parent=0 and even an adaptation of this, with no luck.

Any ideas?

[EDIT]
I’m using a custom taxonomy called Collections, so putting 'collection' => 'vip' into the query means it will only show this collection. I’m thinking if there’s a way of reversing this so it excludes the collection instead?

As it’s not possible to list all of the categories that will appear here as they will be changing all of the time.

[EDIT 2]
After the discussion in the comments below, here’s the updated code.

$ex = array(
    'taxonomy' => 'collection',
    'child_of' => 98,
    'hide_empty' => 0
);
$categories = get_categories($ex);

$categoriesToExclude = array();
foreach ($categories as $category) {
    $categoriesToExclude[] = $category->cat_ID;
}

echo('<pre>'); var_dump($categories);


$args = array(
    'post_type' => 'sell_media_item',
    'category__not_in' => $categoriesToExclude,
    'orderby' => 'desc',
    'paged' => $paged,
    'posts_per_page' => 20
); ?>

<?php echo('<br /><pre>'); var_dump($args); ?>

<?php $loop = new WP_Query( $args ); ?>

Related posts

Leave a Reply

3 comments

  1. I would get the list of all sub categories with get_categories() and then build a 'cat' exclusion array based on the results.

    $args = array('parent' => 98);
    $categories = get_categories($args);
    
    $categoriesToExclude = array();
    foreach ($categories as $category) {
        $categoriesToExclude[] = $category->cat_ID;
    }
    
    
    $args = array(
        'post_type' => 'sell_media_item',
        'category__not_in' => $categoriesToExclude,
        'orderby' => 'desc',
        'paged' => $paged,
        'posts_per_page' => 20
    ); ?>
    
    <?php $loop = new WP_Query( $args ); ?>
    

    This is just an example, you may have to modify it slightly to fit your needs.

  2. So!

    It appears I was trying to do the impossible. I couldn’t get this script working for the life of me. So I tried a different angle. Instead of excluding a custom taxonomy and its terms, I decided to move all of my other terms into a parent term and just called that instead.

    Here’s the code if anyone’s interested…

    <?php $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;               
    
    $args = array(
        'post_type' => 'sell_media_item',
        'taxonomy' => 'collection',
        'term' => 'clubs',
        'orderby' => 'desc',
        'paged' => $paged,
        'posts_per_page' => 20
    );
    
    
    $loop = new WP_Query( $args );
    
    if ( $loop->have_posts() ) : while ($loop->have_posts()) : $loop->the_post(); ?>
    
  3. I wrote my own function in order to exclude subcategory posts from the loop, using tips from the above post and elsewhere.

    In my theme archive.php file, above the loop, I list the subcategories (optional):

        <?php
           $current_cat = get_queried_object();
    
           $args = array( 'parent'=>$current_cat->term_id, 'child_of' => $current_cat->term_id, );
            $categories = get_categories( $args );
            foreach($categories as $category) { ?>
    
               <h2><?php echo $category->name ;?></h2>
               <p> etc....</p>
          <?php } ?>
    

    In my functions.php file, I’ve added the following custom function using pre_get_posts:

    add_action( 'pre_get_posts', 'main_query_without_subcategory_posts' );
    
    function main_query_without_subcategory_posts( $query ) {
    
    if ( ! is_admin() && $query->is_main_query() ) {
        // Not a query for an admin page.
        // It's the main query for a front end page of your site.
    
        if ( is_category() ) {
    
       //Get the current category
            $current_category = get_queried_object();
            //get the id of the current category
            $current_cat_id = $current_category->term_id;
    
            //find the children of current category
            $cat_args = array( 'parent'=>$current_category->term_id, 'child_of' => $current_category->term_id, );
            $subcategories = get_categories( $cat_args );
    
            //Get a list of subcategory ids, stick a minus sign in front
            $subcat_id = array();         
            foreach($subcategories as $subcategory) { 
                $subcat_id[] = " -". $subcategory->term_id; 
            }
    
            //join them together as a string with a comma seperator          
            $excludesubcatlist = join(',', $subcat_id);
    
           //If you have multiple parameters, use $query->set multiple times
            $query->set( 'posts_per_page', '10' );
            $query->set( 'cat', ''.$current_cat_id.','.$excludesubcatlist.'' );
          }
        }
      }
    

    Then in the archive.php, below the subcategories, I’ve added the regular WordPress loop which is now being modified by the above function:

    <?php  while (have_posts() ) : the_post(); ?>
         <h2><?php the_title();?></h2>
         <p> etc....</p>
     <?php endwhile;?>
    

    Though the WordPress codex says that using “category__in” will exclude posts from subcategories, that didn’t work for me and subcategory posts were still showing.

    https://codex.wordpress.org/Class_Reference/WP_Query#Category_Parameters

    https://developer.wordpress.org/reference/hooks/pre_get_posts/