Entity view (Content)

Custom taxonomy term pages

By smullins
Aug. 10, 2011

Although Drupal's taxonomy module very thoughtfully provides a term page which lists all nodes tagged with that term, site builders often want to customize what is displayed on the term page. Of course, you could just ignore the default term page at taxonomy/term/% and build your own page, but then the term links so nicely provided on node pages and through views fields will not be the ones you want to use and you will have to output all term links yourself. Here are three ways to override the default term page. The first way simply uses a view. The second uses a hook provided by the taxonomy module to alter term page paths. The third uses hook_menu_alter() to take over the whole menu callback for term pages.

1. Override the callback for the term path using views (Drupal 6 and 7) Because the views module has a weight of 10, its hooks get called later than core and many contrib modules. This means views can override the callback for existing paths. If I build a view with a page display and give it a path of taxonomy/term/%, my views display will show up when I navigate to taxonomy/term/%, not the default term page. Given that I can access template files for my view and use views headers, footers, attachments, etc.. this option could fulfill many custom requirements.

Building Rich Internet Apps with Drupal & HTML5
Learn the power of combining Drupal + HTML5 + CSS3 + JS

 

2. Use hook_term_path() to link terms to a different path (Drupal 6 only) I can also have my module change the default path for term pages. (For example, in one case the term page was meant to link to a corresponding node page.) The taxonomy module provides a hook for this: hook_term_path() will allow my module to override the default taxonomy term path only for vocabularies which have my module declared in the module column of the vocabulary table. So if I want hook_term_path() to be called I must update the vocabulary table to give my module responsibility, so to speak, for any specific vocabularies whose term path I want to control.

/**
 * Implementation of hook_term_path().
 */
function mymodule_term_path($term) {
  // Return the term path.
  return 'somepath/' . $term->tid; 
}

Now, anywhere taxonomy terms are output as links by Drupal (eg. in views, on node pages, on the taxonomy admin pages, ...), the user will be directed to the term pages provided by my module. The correct path for each term is returned by the function taxonomy_term_path(), which checks to see which module is responsible for the term's vocabulary. If outputting the links myself, I also use taxonomy_term_path().

$keyword[] = l($term->name, taxonomy_term_path($term));

Note for Drupal 7: taxonomy_term_path() is replaced by taxonomy_term_uri() which returns an array containing the term path.

3. Override the page callback and/or access callback for taxonomy/term/% (Drupal 6 and 7) Another option is to override the page callback for term pages using hook_menu_alter(). This gives me unlimited freedom to display whatever I want when the default taxonomy term path (taxonomy/term/%) is called. I can also override the access callback if I want to set some custom limits on who can see the term pages.

/**
 * Implementation of hook_menu_alter().
 */
function mymodule_menu_alter(&$menu) {

  if (isset($menu['taxonomy/term/%'])) {
    $menu['taxonomy/term/%']['page callback'] = 'mymodule_term_page';
    $menu['taxonomy/term/%']['access callback'] = 'mymodule_access_term_pages';
    $menu['taxonomy/term/%']['access arguments'] = array(2);    
  }
}

In my callback function, I can check the term's vocabulary and return something different for each vocabulary. I can also return the default term page provided by the taxonomy module for vocabularies whose term pages I don't want to alter.

/**
 * Callback function for taxonomy/term/%.
 *
 * @param $tid
 *   The term id.
 * 
 * @return
 *   Themed page for a taxonomy term, specific to the term's vocabulary.
 */
function mymodule_taxonomy_term_page($tid) {

  $term = taxonomy_get_term($tid);
  $vocabulary = taxonomy_vocabulary_load($term->vid);
  
  switch($vocabulary->name) {
    case 'Keyword':
      // Returns a custom view.
      return views_embed_view('projects', 'term_block', $tid);
    case 'Subject':
      // Returns a page themed by mymodule.
      return mymodule_subject_page($tid);
    default: 
      // Returns the default term page provided by taxonomy module.
      module_load_include('inc', 'taxonomy', 'taxonomy.pages');
      return taxonomy_term_page($tid);
  }
}

In granting users access to term pages, as with the page callback, I can treat each vocabulary differently if requirements demand it.

/**
 * Access callback function for taxonomy/term/%.
 *
 * @param $tid
 *   The term id.
 * 
 * @return
 *   True if current user is granted access, FALSE otherwise.
 */
function mymodule_access_term_pages($tid) {
  
  $term = taxonomy_get_term($tid);
  $vocabulary = taxonomy_vocabulary_load($term->vid);

  switch($vocabulary->name) {
    case 'Keyword':
    case 'Subject':
      return user_access('access content');
    default:
      return user_access('administer taxonomy');
  }  
}

As an example of taxonomy term information which may be available, here is a helper function which I used to return term details. (Drupal 6)

/**
 * Helper function to get term details ready for term pages.
 *
 * @param $tid
 *   The term id.
 *
 * @return
 *   An array of term details.
 */
function _my_module_get_term_details($tid) {

  $term = taxonomy_get_term($tid);
 
  $vars['description'] = $term->description;
  $vars['synonyms'] = implode(', ', taxonomy_get_synonyms($tid));
  $related = taxonomy_get_related($tid);
  foreach ($related as $related_term) {
    $related_terms[] = $related_term->name;
  }
  $vars['related_terms'] = implode(', ', $related_terms);
 
  if (user_access('administer taxonomy')) {
    $vars['edit_link'] = l('Edit term', 'admin/content/taxonomy/edit/term/' . $tid);
  }

  return $vars;
}

Please add your ideas on customizing term pages, if you feel so inclined, especially if you have experience working with taxonomy in Drupal 7.

Post Tags: