Friday, December 17, 2010

Drupal: Showing related content based on taxonomy

Everyone knows that the taxonomy module allows one to categorize your content using both tags and administrator defined terms and is very flexible for classifying content. You can create one free-tagging vocabulary for everything, or separate controlled vocabularies to define the various properties of your content.

By using views in conjunction with taxonomy, one can easily create a block of related content.

For example on www.OyeStyle.com, we have articles categorized by one vocabulary called as "Main" and another vocabulary called as "Subcategory". These contain a fixed set of terms. We also allow a taxonomy with free-flowing tags for that much more flexibility and further categorization.We wanted to show a block of related articles based on the taxonomy on each page and of-course views was the answer. The link here at http://drupal.org/node/65375 details out as to how to go about it for D5 and D6.

However due to the free-tagging entries, we were ending up with a long list of articles diluting the "meaning" of related content in some ways. Here is how you can pick up related content by using specific taxonomies by avoiding free tags:

After following the instructions above in the drupal link, go to your view and edit the "Taxonomy: Term ID" argument. We then need to modify the PHP code specified for the default argument handling. Modify it thus:

$node = node_load(arg(1));
if ($node && $node->type == 'article' && $node->taxonomy) {
foreach($node->taxonomy as $term) {
$vocab = taxonomy_vocabulary_load($term->vid);
  if (empty($vocab->tags))
      $terms[] = $term->tid;
}
return implode('+' , $terms);
} else { return; }

The key difference in the above code is that for each taxonomy term associated with the node, we are getting the vocabulary associated with it . We then check if this vocabulary allows free tagging and ignore it if so (the empty($vocab->tags) check does this). Do not worry about the performance implications here, the vocabulary will most probably be cached across future calls. One can possibly do other modifications to the above code. For example, lets say you only want terms from a specific vocabulary. That can be done by:

$specific_vocab_name = 'Main';

$vocab = taxonomy_vocabulary_load($term->vid);
  if (strtolower($vocab->name) == strtolower($specific_vocab_name))
      $terms[] = $term->tid;


The above code will only pick terms belonging to the 'Main' vocabulary.Basically modify the vocabulary checks appropriately to get the desired results.

I hope this was useful. Check out the working functionality on Oyestyle by browsing through the articles there! :)