Last updated March 27, 2009. Created on March 16, 2009.
Edited by LeeHunter, Steven Jones, druvision. Log in to edit this page.

This PHP snippet displays all top-level taxonomy terms in a page or a block.

For each term, the count of sub-terms is displayed.

The code is using the taxonomy API, so it's compatible with taxonomy_redirect (verified). It should also be compatible with other add-on modules which change the term path.

$vid = 3;
$terms = taxonomy_get_children(0, $vid);
if (count($terms)) {
  echo '<ul>';
  foreach ($terms as $term){
    echo "<li>" . l($term->name, taxonomy_term_path ($term)) ;
    $children = taxonomy_get_children($term->tid, $vid);
    $cnt = count($children);
    if ($cnt) echo " ($cnt)";
    echo "</li>";
  echo '</ul>';

Looking for support? Visit the forums, or join #drupal-support in IRC.


Summit’s picture

Hi, See no ask question this way, sorry if not appropriate..
Does somebody know how to use above code and bring it through $block->content to use it themable in "panels" delegator custom php content?
Thanks a lot in advance, greetings, Martijn

fehin’s picture

Is there a way to get this to show only the top level term under the vocabulary and list it's children in hierachy form? Right now it lists all terms under the vocabulary in one long list. Thanks.

lindsayo’s picture

I'd love to know that, too.

venusrising’s picture

me too


Marko B’s picture

here u go, put this into block, put vid on second line and u have it. this is from block snipets on

// The ID of the taxonomy vocabulary for which you'd like to create a nested list
$vid = 2;
$debug = false;
// Dado un elemento reconstruido con sus children enlazados,
// busca entre sus hijos y va añadiendo los ids estos útlimos
// al array buffer pasado por referencia.
function fill_children_ids_recursive(&$term_rebuilt, &$children_ids) {
    global $debug;

    if ($term_rebuilt["children_count"]>0) {
        for ($i=0;$i<$term_rebuilt["children_count"];$i++) {
            if ($debug) {
            if (!in_array($term_rebuilt["children"][$i]["id"], $children_ids)) {
            fill_children_ids_recursive($term_rebuilt["children"][$i], $children_ids);

// Los terminos que nos devuelve esta función no tienen hijos enlazados
// con lo que nos vemos obligados a reconstruir la matriz de términos
// para enlazar también los hijos.
$tree = taxonomy_get_tree($vid);
$terms = array();
// Reconstruimos el array de terminos
// añadiendo algunos campos que nos hacen falta
// y que no están establecidos por defecto.
foreach ($tree as &$term) {
    $terms[] = array(
foreach ($terms as $key => &$term_rebuilt) {
    for ($x=0;$x<sizeof($term_rebuilt["parents"]);$x++) {
        $parent_tid = $term_rebuilt["parents"][$x];

        $not_found = true;
        while($not_found&&($idx<sizeof($terms))) {
            if ($terms[$idx]["id"]==$parent_tid) {
                if ($debug) {
                    echo "<pre>found: \$idx = $idx\n";
                    echo "</pre>";
                $not_found = false;

if ($debug) {
    echo "<pre>Arbol de elementos recontruidos\n\n";
    echo "</pre>";

// Creación de la lista HTML.
print "<ul><li>";

$depth = 2;
foreach($terms as $index => &$term_rebuilt) {
    // Para cada elemento reconstruido se buscan los ids de los
    // hijos, no importa a qué nivel de profundad.
    $children_ids = array();
    fill_children_ids_recursive($term_rebuilt, $children_ids);

    // Con los ids de los hijos consultamos para que nos devuelva
    // el número de nodos que cuelgan tanto directamente de el cómo
    // de sus hijos.
    $sql_count = "SELECT COUNT(nid) FROM {term_node} WHERE tid = '".$term_rebuilt["id"]."' ";   
    if (sizeof($children_ids)>0) {
        $sql_count .= " OR tid = '";
        $sql_count .= join("' OR tid = '",$children_ids);
        $sql_count .= "'";
    if ($debug) {
        echo "<pre>SQL for term: ".$term_rebuilt["name"]." -> ".$sql_count."\n</pre>";
    $term_rebuilt["global_node_count"] = db_result(db_query($sql_count));

    // Se expulsa la lista.
    if ($term_rebuilt["depth"] > $depth) {
        print '<ul>';
        $depth = $term_rebuilt["depth"];
    if ($term_rebuilt["depth"] < $depth) {
        for ($i=($depth - $term_rebuilt["depth"]);$i>=1;$i--) {
        print '</ul></li>';
        $depth = $term_rebuilt["depth"];
    print '<li>' . l($term_rebuilt["name"], 'rep/term/' .$term_rebuilt["id"]) . " (".$term_rebuilt["global_node_count"].")";

for ($i=$depth; $i>=0; $i--)
      print "</li>\n</ul>\n";

if ($debug) {
    echo "<pre>Arbol original, obtenido por: taxonomy_get_tree\n\n";
    echo "<pre>";