For example, I have WooCommerce products that have taxonomies:
- brand (e.g. Converse, adidas, D&G) (taxonomy id: product_brand)
- category (e.g. Boots, Sneakers, Sandals, Heels) (taxonomy id: product_cat)
Of course, not every brand includes all categories.
I need to list the categories by brand. (something similar to what Zappos does. E.g.:
Converse - Sandals (2) - Sneakers (6) D&G - Boots (10) - Heels (4) - Sandals (7)
Is there any light way to do this except looping through all products with specific brand and checking for its category?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
To get a list of all terms of taxonomy X whose posts are associated to terms from taxonomy Y too, we have to:
- Get all term IDs for both taxonomies
- Create a tax query to fetch all posts, because we don’t want to show empty term archives.
- Format the result in a hierarchical list.
Let’s go!
-
Getting the term IDs is simple:
get_terms( $taxonomy_name, array( 'fields' => 'ids' ) )
We just have to do that two times (for each taxonomy once).
-
The taxonomy query needs a relationship
ANDto make sure all posts we get are in both taxonomies:'tax_query' => array ( 'relation' => 'AND', array( 'taxonomy' => $first, 'field' => 'id', 'terms' => get_terms( $first, array( 'fields' => 'ids' ) ) ), array( 'taxonomy' => $second, 'field' => 'id', 'terms' => get_terms( $second, array( 'fields' => 'ids' ) ) ), ), -
For formatting, we create an array where the terms of the first taxonomy are the keys and the terms of the second taxonomy are the values. Then we build a nested list with plain
<ul>elements.
Now the function: I have used tags and categories as taxonomies, just because it was easier to test.
function double_term_tree(
$post_types = array( 'post', 'page' ),
$first = 'category',
$second = 'post_tag'
)
{
$query = new WP_Query(
array (
'numberposts' => -1,
'suppress_filters' => TRUE,
'posts_per_page' => -1,
'post_type' => $post_types,
'tax_query' => array (
'relation' => 'AND',
array(
'taxonomy' => $first,
'field' => 'id',
'terms' => get_terms( $first, array( 'fields' => 'ids' ) )
),
array(
'taxonomy' => $second,
'field' => 'id',
'terms' => get_terms( $second, array( 'fields' => 'ids' ) )
),
),
)
);
if ( empty ( $query->posts ) )
return;
$result_list = array();
$output = '<ul>';
foreach ( $query->posts as $post )
{
$first_terms = get_the_term_list( $post->ID, $first, '', '|' );
$second_terms = get_the_term_list( $post->ID, $second, '', '|' );
$f_term_array = explode( '|', $first_terms );
$s_term_array = explode( '|', $second_terms );
foreach ( $f_term_array as $f_term )
{
if ( ! isset ( $result_list[ $f_term ] ) )
$result_list[ $f_term ] = array();
$result_list[ $f_term ] = array_merge( $result_list[ $f_term ], $s_term_array );
}
}
foreach ( $result_list as $k => $v )
{
$result_list[ $k ] = array_unique( $v );
$output .= "n<li>$knt<ul>ntt<li>"
. join( "</li>ntt<li>", array_unique( $v ) )
. "</li>nt</ul>n</li>";
}
$output .= '</ul>';
return $output;
}
You can call this function like this:
echo double_term_tree( 'product', 'brand', 'category' );
And then you get that tree.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0