Community Documentation

taxonomy_get_tree

5 taxonomy.module taxonomy_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL)
6 taxonomy.module taxonomy_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL)
7 taxonomy.module taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $load_entities = FALSE)
8 taxonomy.module taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $load_entities = FALSE)

Create a hierarchical representation of a vocabulary.

Parameters

$vid: Which vocabulary to generate the tree for.

$parent: The term ID under which to generate the tree. If 0, generate the tree for the entire vocabulary.

$max_depth: The number of levels of the tree to return. Leave NULL to return all levels.

$load_entities: If TRUE, a full entity load will occur on the term objects. Otherwise they are partial objects queried directly from the {taxonomy_term_data} table to save execution time and memory consumption when listing large numbers of terms. Defaults to FALSE.

Return value

An array of all term objects in the tree. Each term object is extended to have "depth" and "parents" attributes in addition to its normal ones. Results are statically cached. Term objects will be partial or complete depending on the $load_entities parameter.

▾ 12 functions call taxonomy_get_tree()

ForumTestCase::testAddOrphanTopic in modules/forum/forum.test
Forum nodes should not be created without choosing forum from select list.
forum_forum_load in modules/forum/forum.module
Returns a tree of all forums for a given taxonomy term ID.
hook_options_list in modules/field/modules/options/options.api.php
Returns the list of options to be displayed for a field.
TaxonomyTermTestCase::testNodeTermCreationAndDeletion in modules/taxonomy/taxonomy.test
Test term creation with a free-tagging vocabulary from the node form.
TaxonomyTermTestCase::testTermReorder in modules/taxonomy/taxonomy.test
Save, edit and delete a term using the user interface.
TaxonomyTermUnitTest::testTaxonomyVocabularyTree in modules/taxonomy/taxonomy.test
Test a taxonomy with terms that have multiple parents of different depths.
taxonomy_allowed_values in modules/taxonomy/taxonomy.module
Returns the set of valid terms for a taxonomy field.
taxonomy_check_vocabulary_hierarchy in modules/taxonomy/taxonomy.module
Checks and updates the hierarchy flag of a vocabulary.
taxonomy_form_term in modules/taxonomy/taxonomy.admin.inc
Form function for the term edit form.
taxonomy_overview_terms in modules/taxonomy/taxonomy.admin.inc
Form builder for the taxonomy terms overview.
taxonomy_overview_terms_submit in modules/taxonomy/taxonomy.admin.inc
Submit handler for terms overview form.
_forum_parent_select in modules/forum/forum.admin.inc
Returns a select box for available parent terms

File

modules/taxonomy/taxonomy.module, line 970
Enables the organization of content into categories.

Code

<?php
function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $load_entities = FALSE) {
  $children = &drupal_static(__FUNCTION__, array());
  $parents = &drupal_static(__FUNCTION__ . ':parents', array());
  $terms = &drupal_static(__FUNCTION__ . ':terms', array());

  // We cache trees, so it's not CPU-intensive to call get_tree() on a term
  // and its children, too.
  if (!isset($children[$vid])) {
    $children[$vid] = array();
    $parents[$vid] = array();
    $terms[$vid] = array();

    $query = db_select('taxonomy_term_data', 't');
    $query->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid');
    $result = $query
      ->addTag('translatable')
      ->addTag('term_access')
      ->fields('t')
      ->fields('h', array('parent'))
      ->condition('t.vid', $vid)
      ->orderBy('t.weight')
      ->orderBy('t.name')
      ->execute();

    foreach ($result as $term) {
      $children[$vid][$term->parent][] = $term->tid;
      $parents[$vid][$term->tid][] = $term->parent;
      $terms[$vid][$term->tid] = $term;
    }
  }

  // Load full entities, if necessary. The entity controller statically
  // caches the results.
  if ($load_entities) {
    $term_entities = taxonomy_term_load_multiple(array_keys($terms[$vid]));
  }

  $max_depth = (!isset($max_depth)) ? count($children[$vid]) : $max_depth;
  $tree = array();

  // Keeps track of the parents we have to process, the last entry is used
  // for the next processing step.
  $process_parents = array();
  $process_parents[] = $parent;

  // Loops over the parent terms and adds its children to the tree array.
  // Uses a loop instead of a recursion, because it's more efficient.
  while (count($process_parents)) {
    $parent = array_pop($process_parents);
    // The number of parents determines the current depth.
    $depth = count($process_parents);
    if ($max_depth > $depth && !empty($children[$vid][$parent])) {
      $has_children = FALSE;
      $child = current($children[$vid][$parent]);
      do {
        if (empty($child)) {
          break;
        }
        $term = $load_entities ? $term_entities[$child] : $terms[$vid][$child];
        if (isset($parents[$vid][$term->tid])) {
          // Clone the term so that the depth attribute remains correct
          // in the event of multiple parents.
          $term = clone $term;
        }
        $term->depth = $depth;
        unset($term->parent);
        $term->parents = $parents[$vid][$term->tid];
        $tree[] = $term;
        if (!empty($children[$vid][$term->tid])) {
          $has_children = TRUE;

          // We have to continue with this parent later.
          $process_parents[] = $parent;
          // Use the current term as parent for the next iteration.
          $process_parents[] = $term->tid;

          // Reset pointers for child lists because we step in there more often
          // with multi parents.
          reset($children[$vid][$term->tid]);
          // Move pointer so that we get the correct term the next time.
          next($children[$vid][$parent]);
          break;
        }
      } while ($child = next($children[$vid][$parent]));

      if (!$has_children) {
        // We processed all terms in this hierarchy-level, reset pointer
        // so that this function works the next time it gets called.
        reset($children[$vid][$parent]);
      }
    }
  }

  return $tree;
}
?>

Comments

print_r($result);

Structure of print_r($results), circa Drupal 7:

Array
(
    [0] => stdClass Object
        (
            [tid] => 1
            [vid] => 2
            [name] => About Us
            [description] =>
            [format] => wysiwyg_editor
            [weight] => 0
            [depth] => 0
            [parents] => Array
                (
                    [0] => 0
                )

        )

    [1] => stdClass Object
        (
            [tid] => 2
            [vid] => 2
            [name] => Stories
            [description] =>
            [format] => wysiwyg_editor
            [weight] => 0
            [depth] => 0
            [parents] => Array
                (
                    [0] => 0
                )

        )

)

Some fields above may be from contributed modules and not included in the default, but the structure should still be useful for reference.

Using taxonomy_get_tree() to build a taxonomy menu block

In case anyone needs to build a taxonomy menu (block) using this function here's one way to do it:

<?php
function mymodule_block_info() {
 
$blocks['taxonomy_menu'] = array(
   
'info' => t('Taxonomy menu'),
  );

  return
$blocks;
}

function
mymodule_block_view($delta = '') {
 
$block = array();
 
 
// Taxonomy menu block.
 
if ($delta == 'taxonomy_menu') {
   
$terms = taxonomy_get_tree(1); // Use the correct vocabulary id.
   
    // Get the active trail tid-s.
   
$active = arg(2);
   
$active_parents = taxonomy_get_parents_all($active);
   
$active_parents_tids = array();
    foreach (
$active_parents as $parent) {
     
$active_parents_tids[] = $parent->tid;
    }
   
   
// Build the menu.
   
$term_count = count($terms);
   
$cont = '<ul class="taxonomy_menu">';
    for (
$i = 0; $i < $term_count; $i++) {
     
// Build the classes string.
     
$classes = '';
     
$children = taxonomy_get_children($terms[$i]->tid);
     
$active_trail = in_array($terms[$i]->tid, $active_parents_tids);
      if (
$active_trail && $children) $classes .= 'expanded active-trail ';
      elseif (
$active_trail) $classes .= 'active-trail ';
      elseif (
$children) $classes .= 'collapsed ';
     
      if (
$i == 0) $cont .= '<li class="first '.$classes.'">'.l($terms[$i]->name, 'taxonomy/term/'.$terms[$i]->tid);
      else {
        if (
$terms[$i]->depth == $depth) $cont .= '</li><li class="'.$classes.'">'.l($terms[$i]->name, 'taxonomy/term/'.$terms[$i]->tid);
        elseif (
$terms[$i]->depth > $depth) $cont .= '<ul class="level-'.$terms[$i]->depth.'"><li class="first '.$classes.'">'.l($terms[$i]->name, 'taxonomy/term/'.$terms[$i]->tid);
        elseif (
$terms[$i]->depth < $depth) {
         
// Add missing end-tags depending of depth level difference.
         
for ($j = $terms[$i]->depth; $j < $depth; $j++) {
           
$cont .= '</li></ul>';
          }
         
$cont .= '</li><li class="'.$classes.'">'.l($terms[$i]->name, 'taxonomy/term/'.$terms[$i]->tid);
        }
       
// If we have reached the last element add all possibly missing end-tags.
       
if (!isset($terms[$i+1])) {
          for (
$j = 0; $j < $terms[$i]->depth; $j++) {
           
$cont .= '</li></ul>';
          }
        }
      }
     
$depth = $terms[$i]->depth;
    }
   
$cont .= '</li></ul>';
   
   
// Set the menu html as block content.
   
$block['content'] = array('#markup' => $cont);
  }
 
  return
$block;
}
?>

In your css file you can use 'ul.taxonomy_menu li.collapsed ul {display: none;}' to make it collapsible. Note that the optional $parent, $max_depth, $load_entities parameters (when calling taxonomy_get_tree) allow you to further customize the menu to fit your needs.

finding vid

$vid = taxonomy_vocabulary_machine_name_load("XXX")->vid;
$terms = taxonomy_get_tree($vid);

to get an array for a form field '#options' from a machine name

Once can use

<?php
/**
* returns a array for use with #options in a form field
* */
function taxonomy_options_array($machine_name) {
 
$v = taxonomy_vocabulary_machine_name_load($machine_name);
 
$terms = taxonomy_get_tree($v->vid);
  foreach (
$terms as $term) {
   
$options[$term->tid] = $term->name;
  }
  return
$options;
}
?>

(maintained at https://gist.github.com/1754684)

Login or register to post comments