3

I want to find all parent ids of a given taxonomy term id recursively, without loading them. Existing taxonomy functions like taxonomy_get_parents_all() and taxonomy_get_parents() are loading the terms.

Since I will be using this result in an API function, it is important for me to get the parents with a minimum performance overhead. All I need to get the parents in a simple array like: $parents = array(6, 3, 2);

2 Answers 2

2

Have a look at taxonomy_get_parents() and taxonomy_get_parents_all().

You could copy most of the functions but skip

$parents[$tid] = taxonomy_term_load_multiple($tids);

to not load the terms.

/**
 * Load a terms parent.
 */
function MODULE_taxonomy_get_parents($tid) {
  $parents = &drupal_static(__FUNCTION__, array());

  if ($tid && !isset($parents[$tid])) {
    $query = db_select('taxonomy_term_data', 't');
    $query->join('taxonomy_term_hierarchy', 'h', 'h.parent = t.tid');
    $query->addField('t', 'tid');
    $query->condition('h.tid', $tid);
    $query->addTag('term_access');
    $query->orderBy('t.weight');
    $query->orderBy('t.name');
    // $tids = $query->execute()->fetchCol();
    // $parents[$tid] = taxonomy_term_load_multiple($tids);
    $tids = $query->execute()->fetchAll();
    $parents[$tid] =  $tids;
  }

  return isset($parents[$tid]) ? $parents[$tid] : array();    
}

/**
 * Load all parents for a term.
 */
function MODULE_taxonomy_get_parents_all($tid) {
  $cache = &drupal_static(__FUNCTION__, array());

  if (isset($cache[$tid])) {
    return $cache[$tid];
  }

  $parents = array();
  if ($term = taxonomy_term_load($tid)) {
    $parents[] = $term;
    $n = 0;
    // while ($parent = taxonomy_get_parents($parents[$n]->tid)) {
    while ($parent = MODULE_taxonomy_get_parents($parents[$n]->tid)) {
      $parents = array_merge($parents, $parent);
      $n++;
    }
  }

  $cache[$tid] = $parents;

  return $parents;
}

If you don't need any access control or sorting you can just query the taxonomy_term_hierarchy table directly.

$query = db_select('taxonomy_term_hierarchy', 'h');
$query->addField('h', 'parent', tid);
$query->condition('tid', $tid);
$query->condition('parent', 0, '!=');
$tids = $query->execute()->fetchAll();
$parents[$tid] =  $tids;
3
  • This returns only the first parent of a given term, not the parents of the parents recursively.
    – Elin Y.
    Jan 25, 2016 at 17:33
  • @ЕлинЙ. I updated the answer so that it returns all parents. Jan 26, 2016 at 9:29
  • Thank you Marcus for your answer. Although it is a valid solution for my question, it is not an effective solution that I'm seeking. It recursively makes a database query for each parent term (which Drupal core is also doing that way). I had already done it in a similar but with a simpler query. I hoped for a solution which makes it with an only one query at all.
    – Elin Y.
    Jan 27, 2016 at 17:15
1

I managed to achieve that as follows:

function MYMODULE_taxonomy_get_parents($tid) {
  $taxonomy_hierarchy = db_query('SELECT tid, parent FROM {taxonomy_term_hierarchy} 
                                  WHERE parent != 0')
                        ->fetchAllKeyed();
  $parent_tids = array();

  while (!empty($taxonomy_hierarchy[$tid])) {
    $tid = $taxonomy_hierarchy[$tid];
    $parent_tids[] = $tid;
  }

  return $parent_tids;
}

I have also added some static caching, but for the brevity I didn't include it in this answer.

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.