5

I need to find a way to list all categories - empty or not - in a hierarchial list - like wp_list_categories - also showing the slug, cat name and a link to edit in the admin.

Here is what I have so far:

$args = array(
        'orderby'   => 'name',
        'order'     => 'ASC',
        'hide_empty'    => '0',
  );

$categories = get_categories($args);

foreach( $categories as $category ) { 

    $cat_ID = $category->term_id;
    $cat_name = $category->name;
    #$cat_desc = $category->description; if ( !$cat_desc { $cat_desc = 'Nada!' } );
    $cat_count = $category->count;

    echo '<p><strong>'.$cat_name.'</strong>';
    echo ' / <a href="' . get_category_link( $cat_ID ) . '" title="' . sprintf( __( "View all posts in %s" ), $cat_name ) . '" ' . '>View ( '. $cat_count . ' posts )</a>  ';
    #echo ' / Desc: '. $cat_desc . '';
    echo ' / <a href="'. get_admin_url().'edit-tags.php?action=edit&taxonomy=category&tag_ID='.$cat_ID.'&post_type=post" title="Edit Category">Edit</a>';
    echo '</p>';  

}

All is good, but not nicely ordered - just an alphabetical list.

4 Answers 4

14

output as unordered list:

<?php

    hierarchical_category_tree( 0 ); // the function call; 0 for all categories; or cat ID  

function hierarchical_category_tree( $cat ) {
    // wpse-41548 // alchymyth // a hierarchical list of all categories //

  $next = get_categories('hide_empty=false&orderby=name&order=ASC&parent=' . $cat);

  if( $next ) :    
    foreach( $next as $cat ) :
    echo '<ul><li><strong>' . $cat->name . '</strong>';
    echo ' / <a href="' . get_category_link( $cat->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $cat->name ) . '" ' . '>View ( '. $cat->count . ' posts )</a>  '; 
    echo ' / <a href="'. get_admin_url().'edit-tags.php?action=edit&taxonomy=category&tag_ID='.$cat->term_id.'&post_type=post" title="Edit Category">Edit</a>'; 
    hierarchical_category_tree( $cat->term_id );
    endforeach;    
  endif;

  echo '</li></ul>'; echo "\n";
}  
?>
10
  • genius! - hide_empty seems to require a numeric value to work, the rest is spot on - thanks!
    – Q Studio
    Commented Feb 8, 2012 at 21:31
  • perhaps unrelated to my original question, but how could I determine the "level" of the category hierarchy each category is on - for example in a 3 level hierarchy, I'd need to get 1, 2 or 3?
    – Q Studio
    Commented Feb 8, 2012 at 22:03
  • pastebin.com/GbZFnytw - depth output added as css class of ul tag
    – Michael
    Commented Feb 8, 2012 at 22:24
  • amazing - is there any way to nest the ul / li's - so that they all wrap around - I'd like to try and get them into an accordion type open / close navigation?
    – Q Studio
    Commented Feb 9, 2012 at 22:50
  • by nesting I meant <ul><li><ul><li></li></ul></li></ul> - I guess you figured that...
    – Q Studio
    Commented Feb 10, 2012 at 9:00
5

A slightly updated version of Michael’s answer to use the more generic get_terms (so you can get custom taxonomies, in this case I wanted the WooCommerce product category taxonomy of product_cat).

echo hierarchical_term_tree();

function hierarchical_term_tree($category = 0)
{
    $r = '';

    $args = array(
        'parent' => $category,
    );

    $next = get_terms('product_cat', $args);

    if ($next) {
        $r .= '<ul>';

        foreach ($next as $cat) {
            $r .= '<li><a href="' . get_term_link($cat->slug, $cat->taxonomy) . '" title="' . sprintf(__("View all products in %s"), $cat->name) . '" ' . '>' . $cat->name . ' (' . $cat->count . ')' . '</a>';
            $r .= $cat->term_id !== 0 ? hierarchical_term_tree($cat->term_id) : null;
        }
        $r .= '</li>';

        $r .= '</ul>';
    }

    return $r;
}

Simplified a little to take out the edit link etc. You can add those as required.

3
  • Error : PHP Catchable fatal error: Object of class WP_Error could not be converted to string. On this line : foreach ($next as $cat) .
    – Mehdi
    Commented Dec 14, 2018 at 2:08
  • This looks nice. How could I modify it to actually show the starting term at the top of the list? Currently, it shows all of the child terms, right? I'm using a non-0 term ID, ie. a valid term ID, not just all of them. Commented Feb 2, 2019 at 10:25
  • @deadlyhifi Nice! Got the job done for me! Thank you.
    – Ruvee
    Commented Apr 5, 2021 at 2:46
0

You can use following code:

$args = array(

    'hide_empty'         => 0,
    'echo'               => 1,
    'taxonomy'           => 'category',
    'hierarchical'  =>1,
    'show_count' => 1,

);

function add_class_wp_list_categories($wp_list_categories) {
        $pattern = '/<li class="/is';
        $replacement = '<li class="first ';
        return preg_replace($pattern, $replacement, $wp_list_categories);
}
add_filter('wp_list_categories','add_class_wp_list_categories');

echo wp_list_categories( $args );
-1

Hmm I think you need to include 'hierarchical' => 1, in your args list. Also you have one comma too much at the end of the args list. After the last argument you do not need a comma :)

Here's a complete example:

$args = array(
        'orderby'   => 'name', 
        'order'     => 'ASC', 
        'hierarchical' => 1,
        'hide_empty'    => '0'
  );
2
  • Read more at codex.wordpress.org/Function_Reference/get_categories :) Commented Feb 7, 2012 at 22:07
  • Thanks - but this does not order them hierarchically - the codex states: -- When true, the results will include sub-categories that are empty, as long as those sub-categories have sub-categories that are not empty. The default is true. Valid values:
    – Q Studio
    Commented Feb 8, 2012 at 21:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.