Modify Taxonomy pages to exclude items in child taxonomies

I found this question:

Theres a way to use $query->set(‘tax_query’ in pre_get_posts filter?

Read More

which seems to indicate that yes, you can alter the taxonomy query on taxonomy archives via pre_get_posts(). so i came up with

add_action('pre_get_posts', 'kia_no_child_terms' );

function kia_no_child_terms( $wp_query ) {  
  if( is_tax() ) {
     $wp_query->tax_query->queries[0]['include_children'] = 0;
  }
}

as well as

add_action('pre_get_posts', 'kia_no_child_terms' );

function kia_no_child_terms( $wp_query ) {
   if( is_tax() ) {
        $tax_query = $wp_query->get( 'tax_query' );
        $tax_query->queries[0]['include_children'] = 0;
    $wp_query->set( 'tax_query', $tax_query );  
    }    
}

to try to set the include_children parameter to false… and just about every combination of the two i can think of. so far however, the taxonomy archive is still showing the items in the child term

and the following test just seems to ADD the additional tax queries instead of overwriting them… which just confuses me.

function dummy_test( $wp_query){
$tax_query = array(
             'relation' => 'OR',
             array(
               'taxonomy' => 'tax1',
               'terms' => array( 'term1', 'term2' ),
               'field' => 'slug',
             ),
             array(
               'taxonomy' => 'tax2',
               'terms' => array( 'term-a', 'term-b' ),
               'field' => 'slug',
             ),
           );


$wp_query->set( 'tax_query', $tax_query );

);
add_action('pre_get_posts','dummy_test');

shouldn’t SET overwrite the current value?

Related posts

Leave a Reply

5 comments

  1. I know this is an old question, but it is a bit confusing and hopefully will help someone. The reason that `$query->set doesn’t work is because the query has already been parsed and now we need to also update the tax_query object also. Here is how I did it:

    function my_tax_query( $query ) {
        $package_id = 12345;
        $tax_query = array(
            'taxonomy' => 'package_id',
            'terms'    => array( $package_id ),
            'field'    => 'slug',
            'operator' => 'IN',
        );
        $query->tax_query->queries[] = $tax_query; 
        $query->query_vars['tax_query'] = $query->tax_query->queries;
    }
    add_action( 'pre_get_posts', 'my_tax_query' );
    
  2. As of WordPress 3.7 a new action named parse_tax_query was added exactly for this purpose.

    function kia_no_child_terms($wp_query) {  
      $wp_query->tax_query->queries[0]['include_children'] = 0;
    }
    add_action('parse_tax_query', 'kia_no_child_terms');
    

    This hook modifies the values of both query_vars and tax_query. Using the pre_get_posts method resulted in duplicate taxonomy queries, at least for me.

    Prior to 3.7 you must use the pre_get_posts action instead, as detailed in the other answers.

  3. I could not get this to work with any combination of pre_get_posts or parse_query. I can do it relatively easily by wiping out the query object after it is made. I don’t like it because then I’m running the query twice, but I’m at my wit’s end with trying to be “efficient.”

    function kia_no_child_taxonomies(){
    
        if(is_tax()){
            $args = array(
                'tax_query' => array(
                    array(
                        'taxonomy' => get_query_var('taxonomy'),
                        'field' => 'slug',
                        'terms' => get_query_var('term'),
                        'include_children' => FALSE
                    )
                )
            );
            query_posts($args); 
        }
    }
    
     add_action('wp','kia_no_child_taxonomies');
    

    So until someone comes along with a better answer, this is the only method I have found so far.

    EDIT:

    Adapting the answer from @Tanner Moushey, I was finally able to make this work to exclude all child terms from a taxonomy archive on the pre_get_posts hook without the inefficient double-query.

    function kia_no_child_taxonomies( $query ) {
    
        if( is_tax() ):
    
        $tax_obj = $query->get_queried_object();
    
       $tax_query = array(
                        'taxonomy' => $tax_obj->taxonomy,
                        'field' => 'slug',
                        'terms' => $tax_obj->slug,
                        'include_children' => FALSE
                );
       $query->tax_query->queries[] = $tax_query;
       $query->query_vars['tax_query'] = $query->tax_query->queries;
    
       endif;
    
    }
    add_action( 'pre_get_posts', 'kia_no_child_taxonomies' );
    
  4. For those who like me were stuck with this issue, I found something useful.
    I used the priority system

        function kia_no_child_taxonomies( $query ) {
    
    if( is_tax() ):
    
    $tax_obj = $query->get_queried_object();
    $tax_query = array(
                    'taxonomy' => $tax_obj->taxonomy,
                    'field' => 'slug',
                    'terms' => $tax_obj->slug,
                    'include_children' => FALSE);
    $query->tax_query->queries[] = $tax_query;
    $query->query_vars['tax_query'] = $query->tax_query->queries;
    return $query;
    endif;
    
    }
     add_action( 'pre_get_posts', 'kia_no_child_taxonomies',0 );
    

    My query wasn’t included in the result and search was broken with my exclusions.
    Hope this will help.

  5. I stumbled upon the following thread on WP Core and am using it successfully to exclude children for a specific taxonomy:

    function wpse_43181_parse_tax_query( $query ) {
      if ( ! empty( $query->tax_query->queries ) ) {
        foreach ( $query->tax_query->queries as &$tax_query ) {
          if ( $tax_query['taxonomy'] === 'your_taxonomy' ) {
            $tax_query['include_children'] = false;
          }
        }
      }
    }
    add_action( 'parse_tax_query', 'wpse_43181_parse_tax_query' );
    

    Tweak it to your liking to exclude children from all taxonomy pages.