I have products as a CPT in Wordpress, and am trying to filter posts based on taxonomies with checkboxes. I have two taxonomies, brands and sizes. They are outputted like this in the index.php file:
<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
<?php
if( $brands = get_terms( array( 'taxonomy' => 'brand' ) ) ) :
foreach( $brands as $brand ) :
echo '<p><input type="checkbox" id="brand_' . $brand->term_id . '" name="brand_' . $brand->term_id . '" /><label for="brand_' . $brand->term_id . '">' . $brand->name . '</label></p>';
endforeach;
endif;
?>
<?php
if( $sizes = get_terms( array( 'taxonomy' => 'sizes' ) ) ) :
foreach( $sizes as $size ) :
echo '<p><input type="checkbox" id="size_' . $size->term_id . '" name="size_' . $size->term_id . '" /><label for="size_' . $size->term_id . '">' . $size->name . '</label></p>';
endforeach;
endif;
?>
<button>Apply filter</button>
<input type="hidden" name="action" value="myfilter">
</form>
In my functions.php file I have the following to build the WP_query and include the taxonomies:
function misha_filter_function(){
$args = array(
'orderby' => 'date',
'post_type' => 'clothing_product',
'posts_per_page' => -1
);
//brand checkboxes
if( $brands = get_terms( array( 'taxonomy' => 'brand' ) ) ) :
$all_terms = array();
foreach( $brands as $brand ) {
if( isset( $_POST['brand_' . $brand->term_id ] ) && $_POST['brand_' . $brand->term_id] == 'on' )
$all_terms[] = $brand->slug;
}
if( count( $all_terms ) > 0 ) {
$args['tax_query'] = array(
array(
'taxonomy' => 'brand',
'field' => 'slug',
'terms'=> $all_terms
)
);
}
endif;
//sizes checkboxes
if( $sizes = get_terms( array( 'taxonomy' => 'sizes' ) ) ) :
$all_terms = array();
foreach( $sizes as $size ) {
if( isset( $_POST['size_' . $size->term_id ] ) && $_POST['size_' . $size->term_id] == 'on' )
$all_terms[] = $size->slug;
}
if( count( $all_terms ) > 0 ) {
$args['tax_query'] = array(
array(
'taxonomy' => 'sizes',
'field' => 'slug',
'terms'=> $all_terms
)
);
}
endif;
$query = new WP_Query( $args );
if( $query->have_posts() ) :
while( $query->have_posts() ): $query->the_post();
echo '<h2>' . $query->post->post_title . '</h2>';
endwhile;
wp_reset_postdata();
else :
echo 'No posts found';
endif;
die();
}
add_action('wp_ajax_myfilter', 'misha_filter_function');
add_action('wp_ajax_nopriv_myfilter', 'misha_filter_function');
And this is the AJAX/jQuery in scripts.js:
jQuery(function($){
$('#filter').submit(function(){
var filter = $('#filter');
$.ajax({
url:filter.attr('action'),
data:filter.serialize(), // form data
type:filter.attr('method'), // POST
beforeSend:function(xhr){
filter.find('button').text('Processing...'); // changing the button label
},
success:function(data){
filter.find('button').text('Apply filter'); // changing the button label back
$('#response').html(data); // insert data
}
});
return false;
});
});
What I have is a semi-working result where checkboxes are created for all available brands and sizes and filtering is possible. The problem is that if size XL and brand Nike are checked, it's pulling all products with size XL, even brands that aren't Nike, which is not what I want.
Looking at the Wordpress Codex,
tax_query takes an array of tax query arguments arrays (it takes an array of arrays). This construct allows you to query multiple taxonomies by using the relation parameter in the first (outer) array to describe the boolean relationship between the taxonomy arrays.
So I'm guessing the two taxonomies should be two separate arrays inside the tax_query array, but can that somehow be combined with the foreach loops?
foreach( $brands as $brand ) {
if( isset( $_POST['brand_' . $brand->term_id ] ) && $_POST['brand_' . $brand->term_id] == 'on' )
$all_terms[] = $brand->slug;
}
Thanks a bunch