Multiple relationship for multiple tax_query in WP_Query

I want to use the WP_Query() class to filter some of my posts. The problem I am facing now is handling the taxonomy query. Normally, the WP_Query() only handle one relationship for tax_query() (either AND or OR), but what I need is mixed use of these relationships on the tax_query(), how can achieve it?
eg

'tax_query' => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'taxonomy1',
            'field' => 'slug',
            'terms' => array( $term )
        ),
        array(
            'taxonomy' => 'taxonomy3',
            'field' => 'slug',
            'terms' => array( $term3 ),
            'operator' => 'IN',
        )
       // below i want to use OR relationship
       'relation' => 'OR',
      array(
            'taxonomy' => 'taxonomy4',
            'field' => 'slug',
            'terms' => array( $term4 )
        ),
        array(
            'taxonomy' => 'taxonomy2',
            'field' => 'slug',
            'terms' => array( $term2 ),
            'operator' => 'IN',
        )
    )  

I know the code above is not working, do I need to use WP_Query() filter to do it? Any idea?

2

This can be done by using the term_taxonomy_id rather than the slug, which will effectively ignore whichever taxonomy is specified and just look at the unique term_taxonomy_id field. This will allow you to effectively be able to do a mixed relationship. You’d want to use an overall relation of AND and put all the terms that should be related OR in one item using the IN operator. You will need to map the terms desired to their term_taxonomy_ids first.

$taxes = array( 'taxonomy1', 'taxonomy2', 'taxonomy3', 'taxonomy4' );

foreach ( $taxes as $tax ) {
    $terms = get_terms( $tax );

    foreach ( $terms as $term )
        $tax_map[$tax][$term->slug] = $term->term_taxonomy_id;
}


$args['tax_query'] => array(
    'relation' => 'AND',
    array(
        'taxonomy' => 'taxonomy1',
        'field' => 'term_taxonomy_id',
        'terms' => array( $tax_map['taxonomy1'][$slug] )
        'operator' => 'IN',
    ),
    array(
        'taxonomy' => 'taxonomy3',
        'field' => 'term_taxonomy_id',
        'terms' => array( $tax_map['taxonomy3'][$slug] ),
        'operator' => 'IN',
    ),
    array(
        'taxonomy' => 'taxonomy4', // gets ignored
        'field' => 'term_taxonomy_id',
        'terms' => array( $tax_map['taxonomy4'][$slug], $tax_map['taxonomy2'][$slug] ),
        'operator' => 'IN',
    ),
);

Note that pre-3.5, you’d also need to specify 'include_children' => false. See this Trac ticket for more: https://core.trac.wordpress.org/ticket/21228

Leave a Comment