Roots Discourse

Refactor my custom taxonomy output

Hello all, I need some help with refactoring again please.
I’ll provide some info first, show my current solution and ask the question at the bottom.

Information
I have a custom parent-child taxonomy which looks like this:
image

I want to display it as a navigation menu which looks like this:
image

Current solution
I worked my way out however I believe there should be much better way to do it. Check out my code below:

  • Controller retrieves the taxonomy and transforms it into two dimensional array.
my soberwp controller. S**t code warning: +18
<?php
public function all_categories() {
        $all_categories_obj = get_terms([
            'taxonomy' => 'dogplace-type',
            'hide_empty' => false,
            'orderby' => 'parent',
            'order' => 'asc',
        ]);

        $categories_array = array_map(function ($category) {
            return [
                'name'     => $category->name,
                'permalink'=> get_term_link($category),
                'id'       => $category->term_id,
                'parent_id'   => $category->parent,
            ];
        }, $all_categories_obj);
        
        foreach($categories_array as $key => $value) {
            if ($categories_array[$key]['parent_id'] === 0) {
                $keys = array_keys(array_column($categories_array, 'parent_id'), $categories_array[$key]['id']);
                foreach ($keys as $subcategory_key) {
                    $categories_array[$key]['subcategories'][] = $categories_array[$subcategory_key];
                }
                if (empty($keys)) {
                    $categories_array[$key]['subcategories'][] = null;
                }
                $categories_menu_items[] = $categories_array[$key];
            }
        }

        return $categories_menu_items;
?>
  • My template is a basic nested foreach loop
Blade template piece
<div class="container bg-grey-lighter p-8">
   <div class="sm:flex mb-4">
      @foreach($all_categories as $category)
      <div class="sm:w-1/4 h-auto">
         <div class="text-orange mb-2">{!! $category['name'] !!}</div>
         <ul class="list-reset leading-normal">
            @foreach($category['subcategories'] as $subcategory)
            <li>{{ $subcategory['name'] }}</li>
            @endforeach
         </ul>
      </div>
      @endforeach
   </div>
</div>
HTML output
<div class="container bg-grey-lighter p-8">
   <div class="sm:flex mb-4">
      <div class="sm:w-1/4 h-auto">
         <div class="text-orange mb-2">Hospitality</div>
         <ul class="list-reset leading-normal">
            <li>Hotel</li>
            <li>Holiday park</li>
            <li>Caffee</li>
            <li>Shop</li>
         </ul>
      </div>
      <div class="sm:w-1/4 h-auto">
         <div class="text-orange mb-2">Outdoors</div>
         <ul class="list-reset leading-normal">
            <li>Beach</li>
            <li>Park</li>
            <li>Hiking</li>
         </ul>
      </div>
      <div class="sm:w-1/4 h-auto">
         <div class="text-orange mb-2">Commercial</div>
         <ul class="list-reset leading-normal">
            <li>Grooming</li>
            <li>Vets</li>
            <li>Food</li>
            <li>Kennel</li>
         </ul>
      </div>
      <div class="sm:w-1/4 h-auto">
         <div class="text-orange mb-2">Other</div>
         <ul class="list-reset leading-normal">
            <li></li>
         </ul>
      </div>
   </div>
</div>

Q U E S T I O N
What is the better way to output my custom taxonomy as navigation menu? Thanks

Does this thread help?

foreach( get_terms( 'products-category', array( 'hide_empty' => false, 'parent' => 0 ) ) as $parent_term ) {
  // display top level term name
  echo $parent_term->name . '<br>';

  foreach( get_terms( 'products-category', array( 'hide_empty' => false, 'parent' => $parent_term->term_id ) ) as $child_term ) {
    // display name of all childs of the parent term
    echo $child_term->name . '<br>';
  }

}

But replace the echo part with a one dimensional array in sober controller?
1 Like

That might look like better code but yours is probably faster as you only do one call of get_terms.

1 Like