Dennis
Dennis

Reputation: 538

Nested wordpress terms list - filter

I've made a custom term taxonomy in Wordpress with the plugin CPT UI. So I'm able to add "Product categories" to my Custom Post Type "Product". We have a parent categories and child categories. For example:

*Toegangscontroles


*Spiegels

and so on

So I've create a new page "page-products" to show all the products. This page must contain a filter based on the product categories.

I guess that this page consists out of 2 "loops". One for the filter and one for the products.

Product loop

<?php $args = array('post_type' => 'product'); ?>
<?php $loop = new WP_Query($args); ?>
<?php if ( $loop->have_posts() ) : while ( $loop->have_posts() ) : $loop->the_post(); ?>

    <?php get_template_part( 'loop-templates/content-product' ); ?>

<?php endwhile; ?>
<?php else: ?>
                <h1>
                    <?php
                        _e('Geen producten gevonden','axces-theme');
                    ?>
                </h1>
 <?php endif; ?>
 <?php wp_reset_postdata(); ?>

Terms // Filter *

                <?php
                    $args = array('hide_empty' => false, 'orderby' => 'term_group', 'parent' => false);
                    $terms = get_terms('product_categorie', $args);
                    $hierarchy = _get_term_hierarchy('product_categorie');
                    echo '<ul class="filter">';
                    foreach ($terms as $term) {
                      echo '<li class="parent"><strong class="parent__item">'.$term->name.'</strong>';
                      if (array_key_exists($term->term_id, $hierarchy)) {
                        echo '<ul class="childs">';
                        foreach ($hierarchy[$term->term_id] as $v) {
                          $child = get_term($v);
                          echo '<li class="child" data-filter="'.$child->slug.'">'.$child->name.'</li>';
                        }
                        echo '</ul>';
                      }
                      echo '</li>';
                    }
                    echo '</ul>';
                ?>

But the result of this is not right. I want to have a nested list. Like this:

<ul>
    <li class="parent">Toegangscontroles
        <ul>
            <li class="child">Software</li>
            <li class="child">Wandlezer</li>
        </ul>
    </li>
    <li class="parent">Another parent term
        <ul>
            <li class="child">child term</li>
            <li class="child">child term</li>
        </ul>
    </li>
</ul>

So summarized my issues:

  1. Create a filter on the page-product.php page
  2. Correctly nest the list

Thanks!

Upvotes: 4

Views: 1979

Answers (4)

Bhautik
Bhautik

Reputation: 11272

First, you have to get all parent categories, and then based on parent id you can write a recurring function that gives you the child category of given id. check below code.

function get_child_categories( $parent_category_id ){
    $html = '';
    $child_categories = get_categories( array( 'parent' => $parent_category_id, 'hide_empty' => false, 'taxonomy' => 'product_cat' ) );
    if( !empty( $child_categories ) ){
        $html .= '<ul>';
        foreach ( $child_categories as $child_category ) {
            $html .= '<li class="child">'.$child_category->name;
            $html .= get_child_categories( $child_category->term_id );
            $html .= '</li>';
        }
        $html .= '</ul>';
    }
    return $html;
}

function list_categories(){
    $html = '';
    $parent_categories = get_categories( array( 'parent' => 0, 'hide_empty' => false, 'taxonomy' => 'product_cat' ) );
    $html.= '<ul>';
    foreach ( $parent_categories as $parent_category ) {
        $html .= '<li class="parent">'.$parent_category->name;
        $html .= get_child_categories( $parent_category->term_id  );
        $html .= '</li>';
    }
    $html.= '</ul>';
    return $html;
}
add_shortcode( 'list_categories', 'list_categories' );

Output

  • A - Main category
    • B - Child Category
    • C - Child Category
      • D - Nested Child Category( if available )
  • E - Main category
    • F - Child Category
    • G - Child Category
      • H - Nested Child Category( if available )

Upvotes: 4

Dmitry Leiko
Dmitry Leiko

Reputation: 4412

Use wp_terms_checklist with the 'taxonomy' => 'taxonomy' argument.

$args = array(
    'descendants_and_self'  => 0,
    'selected_cats'         => false,
    'popular_cats'          => false,
    'walker'                => null,
    'taxonomy'              => 'your taxomonomy',
    'checked_ontop'         => true
);
 
<ul>
    <?php wp_terms_checklist(0, $args); ?>
</ul>

Upvotes: 3

Vitali Protosovitski
Vitali Protosovitski

Reputation: 583

HTML is invalid here, however the proper solution is to use the _get_term_hierarchy() function

  $args = array('hide_empty' => 0, 'orderby' => 'term_group');
  $terms = get_terms('category', $args);
  $hierarchy = _get_term_hierarchy('category');
  echo '<ul>';
  foreach ($terms as $term) {
    echo '<li>'.$term->name;
    if (array_key_exists($term->term_id, $hierarchy)) {
      echo '<ul>';
      foreach ($hierarchy[$term->term_id] as $v) {
        $child = get_term($v);
        echo '<li>'.$child->name.'</li>';
      }
      echo '</ul>';
    }
    echo '</li>';
  }
  echo '</ul>';

Upvotes: 1

Mel Macaluso
Mel Macaluso

Reputation: 3810

This will output the taxonomies that are registered for your products:

After that you want a foreach or some iterator to get the terms of each taxonomy like:

<?php 

$taxonomies = get_object_taxonomies( 'Product', 'objects');

foreach($taxonomies as $taxonomy): ?>
  <h2> <?= $taxonomy->label ?> </h2>

  // Get all the single taxonomy terms
  $terms = get_terms( array(
    'taxonomy' => $taxonomy->name,
    'hide_empty' => false,
  ) );

  <ul>
    <?php foreach($terms as $term): ?>
      <li><?= $term->name ?></li>
     <?php endforeach; ?>
  </ul>


<?php endforeach; ?>

Upvotes: 0

Related Questions