Custom taxonomy terms hierarchical navigation
-
22-04-2021 - |
Pergunta
I'm building a product catalog site and I created a product
custom post type and a related product_type
taxonomy. I added some products and created the following product_type
terms:
- Books
- Classics
- Fantasy
- Mystery
- Toys
- Puzzles
- Dolls
- Cars
When a user visits the catalog I want to show him a product_type
terms navigation by level. That is, when he enters the main catalog page I only want him to see the first level of terms: Books, Toys and a special link named All that when clicked shows all products.
When the user clicks one of the root terms, for example, Books, I want to show its child terms in addition to the root terms, that is: Classics, Fantasy, Mystery and a special link named All that when clicked shows all products under the Books term.
Likewise, when the user clicks the Toys root term, I want to show the its child terms in addition to the root terms, that is: Puzzles, Dolls, Cars and a special link named All that when clicked shows all products under the Toys term.
I'm using the following recursive function to get all the terms hierarchically:
function get_taxonomy_hierarchy( $taxonomy, $parent = 0 ) {
$taxonomy = is_array( $taxonomy ) ? array_shift( $taxonomy ) : $taxonomy;
$terms = get_terms( $taxonomy, array( 'parent' => $parent ) );
$children = array();
foreach ( $terms as $term ){
$term->children = get_taxonomy_hierarchy( $taxonomy, $term->term_id );
$children[ $term->term_id ] = $term;
}
return $children;
}
But I'm hitting a wall trying to handle the All links in all of this structure because they are not actual terms per se. Any ideas would be appreciated.
Solução
I managed to find a solution myself. This code is to be used in taxonomy templates.
PHP:
function show_taxonomy_navigation( $post_type = 'post', $taxonomy = 'category', $parent = 0 ) {
$html = get_taxonomy_hierarchy( $post_type, $taxonomy, $parent );
echo $html;
}
function get_taxonomy_hierarchy( $post_type, $taxonomy, $parent = 0, $depth = 0 ) {
$taxonomy = is_array( $taxonomy ) ? array_shift( $taxonomy ) : $taxonomy;
$html = '';
// get the id of the currently queried term
$current_term_id = get_queried_object_id();
$args = array(
'taxonomy' => $taxonomy,
'parent' => $parent,
'order_by' => 'name',
);
// Get the child terms of $parent
$terms = get_terms( $args );
if ( $terms ) {
if ( $depth == 0 ) {
$html .= '<nav class="taxonomy-navigation">';
}
$ul_classes = [];
$ul_classes[] = 'terms';
$html .= '<ul class="' . esc_attr( implode( ' ', array_filter( $ul_classes ) ) ) . '">';
// Add 'All' link
$all_link = ( $parent > 0 ) ? get_term_link( $parent ) : get_post_type_archive_link( $post_type );
$html .= '<li><a href="' . $all_link . '">' . esc_html__( 'All', 'my-taxonomy-navigation' ) . '</a></li>';
foreach ( $terms as $term ) {
$li_classes = [];
$li_classes[] = 'term-item';
// Add class if term corresponds to the currently queried term
$li_classes[] = ( $term->term_id == $current_term_id ) ? 'current-term' : null;
// Add class if term is a parent of the currently queried term
$li_classes[] = ( term_is_ancestor_of( $term->term_id, $current_term_id, $taxonomy ) ) ? 'current-term-parent' : '';
$html .= '<li class="' . esc_attr( implode( ' ', array_filter( $li_classes ) ) ) . '">';
$html .= '<a href="' . get_term_link( $term->term_id ) . '">' . $term->name . '</a>';
// Recursively go deeper in the hierarchy
$html .= get_taxonomy_hierarchy( $post_type, $taxonomy, $term->term_id, $depth + 1 );
$html .= '</a>';
$html .= '</li>';
}
$html .= '</ul>';
if ( $depth == 0 ) {
$html .= '</nav>';
}
}
return $html;
}
CSS:
.taxonomy-navigation ul.terms {
position: relative;
list-style: none;
text-align: center;
}
.taxonomy-navigation ul.terms li {
display: inline-block;
margin: 0;
padding: 0 15px;
}
.taxonomy-navigation ul.terms li.current-term > a,
.taxonomy-navigation ul.terms li.current-term-parent > a {
font-weight: 700;
}
.taxonomy-navigation ul.terms li ul.terms {
display: none;
position: absolute;
top: auto;
left: 0;
right: 0;
margin: 0 auto;
}
.taxonomy-navigation ul.terms li.current-term > ul.terms,
.taxonomy-navigation ul.terms li.current-term-parent > ul.terms {
display: block;
}