Complex/nested/relational tax_query and pre_get_posts troubles

I was recently tasked with modifying the admin search for a WordPress CPT to include a taxonomy dropdown filter that allowed the client to search a property by the number of bedrooms it contains as well as the type of home it was. The client wanted the search behavior to return properties with bedrooms greater than 1 if 1 was selected and greater than 2 if 2 was selected, etc.

During this attempt, I thought it would be an easy modification to the query within pre_get_posts by just building a brand new tax_query but I had a lot of trouble getting it to actually work with strange behaviors all over the place and many of my workarounds failing.

I tried nested complex relations for the tax query:

'tax_query'  => array(
    'relation' => 'AND',
    array(
        array(
            'taxonomy'     => 'home-type',
            'terms'   => ["single-family"],
            'operator' => 'IN',
            'field' => 'slug',
            'include_children' => false
        ),
    ),
    array(
        'relation' => 'OR',
        array(
            'taxonomy'     => 'beds',
            'terms'   => ["5", "6","7","8","9","10"],
            'operator' => 'IN',
            'field' => 'slug',
            'include_children' => false
        )
),

I tried non-complex tax_query modification:

'tax_query'  => array(
    'relation' => 'AND',
    array(
        array(
            'taxonomy'     => 'home-type',
            'terms'   => ["single-family"],
            'operator' => 'IN',
            'field' => 'slug',
            'include_children' => false
        ),
        array(
            'taxonomy'     => 'beds',
            'terms'   => ["5", "6","7","8","9","10"],
            'operator' => 'IN',
            'field' => 'slug',
            'include_children' => false
        )
    )
),

And neither solved the issue. I tried, NOT IN, EXISTS, and AND operator approaches.

I found an older article from 2013 that suggested I back out the use of slug searches and move to term_taxonomy_id searches. This did not solve my issue. I tried switching to name searches, too, but that didn’t help solve the issue.

What did finally work was the unsetting of my taxonomy queries manually from $query->query and $query->query_vars within the reference query:

$tax_query_clone = clone $query->tax_query;
foreach ( $tax_query_clone->queries as $q ) {
   unset($query->query[$q['taxonomy']]);
   unset($query->query_vars[$q['taxonomy']]);
}

Why I believe this worked is because my search data was being passed as GET params and even though I was using this query data to build a completely new tax_query inside of the pre_get_posts hook, the presence of these lookups were also existing as main $query->query search.

In other words, I believe $query was performing two searches, one based on what was in $query->query and another that supplemented the former through my new tax_query.

UPDATE:

I discovered I had conflicting code that was modifying the query using parse_query. This code was related to prior taxonmy filter work that was implementing following this method

Here is a simplified look into the working method running in `pre_get_posts`

public static function modify_search_query( $query ) {

        if ( !$query->is_main_query() || !is_admin() ) {
            return;
        }

        if ( $query->get( 'post_type') !='property' )  {
            return;
        }

        $tax_query_clone = clone $query->tax_query;
        $tax_query_and = array('relation' => 'AND');

        foreach ( $tax_query_clone->queries as $q ) {

            unset($query->query[$q['taxonomy']]);
            unset($query->query_vars[$q['taxonomy']]);

            $q['include_children'] = false;
            $q['field'] = 'slug';
            $q['operator'] = 'IN';

            switch($q['taxonomy']) {
                
                case 'beds':
                case 'baths':
                    $terms = get_terms($q['taxonomy'] , ['hide_empty' =>false]);
                    
                    $int =  (float) str_replace("-", "." , $q['terms'][0]);
                    $in = [];
                           
                    foreach($terms as $t) {
                       if ( $int <= (float) $t->name ) {
                           $in[] = (string) $t->slug;
                       }
                    }
                            
                    $tax_query_and[] =  [
                       'taxonomy'=> $q['taxonomy'],
                        'field' => 'slug',
                        'terms'=> $in, 
                        'operator' => "IN",
                        'include_children' => false
                    ];
                          

                    break;
            }
            
        }


        $tax_query = [];

        if (count($tax_query_and)>1) {
            $tax_query = $tax_query_and;
        }


        $query->set('tax_query' , $tax_query);
      
        echo "<pre style='display:none;'>";
        echo "AND\r\n";
        print_r($tax_query_and); 
        echo "TAX QUERY\r\n";
        print_r($tax_query);
        echo "QUERY\r\n";
        print_r($query);
        echo "</pre>";

    }

Hudson Atwell

https://discord.gg/yaQjenbhGB

Related Posts

Leave a Reply

© 2023 @atwellpublive - Theme by WPEnjoy · Powered by WordPress