background image
HomeRecent PostsDrupalSearchTagsRSSContactAboutAccount
Eric.London's picture

Taxonomy is a great way of categorizing your content, and in this case we'll take it a step further to organize your content and create a dynamic layout. In a recent situation, we created a taxonomy category for a given node type and assigned 4 terms to the category. The node type contained an image field and a description. We wanted to show a view all the node images, but categorized by taxonomy term. I thought the best way to accomplish this was to get a list of all the taxonomy terms, loop through them, pass the term ID as an argument to a view, and output each view's html dynamically. In the following code snippet, I created a module that generates a block [see below]

When creating your view, make sure you add an argument for "Taxonomy: Term ID". In my example, I selected "Use empty text" for the default argument option to prevent taxonomy terms from being shown if they do not have any matching nodes.

<?php
function MYMODULE_block($op='list', $delta=0) {
 
$block = array();
  switch (
$op) {
    case
'list':
     
$block[0]['info'] = t('MYBLOCKTITLE');
      return
$block;
      break;
    case
'view':
     
$block['subject'] = NULL;
     
$block['content'] = NULL;
     
$block_content = "";
     
     
// define vocab name
     
$vocabName = 'MYCATEGORYNAME';

     
// define view name
     
$viewName = 'MYVIEWNAME';

     
// define node type
     
$nodeType = 'MYNODETYPE';

     
// get vocabularies for this node
     
$vocabs = taxonomy_get_vocabularies($nodeType));     
     
     
// ensure vocabs exist
     
if (count($vocabs)==0 || !$vocabs) return $block;

     
// loop through vocabs and look for matching name
     
foreach ($vocabs as $k => $v) {
        if (
$v->name == $vocabName) {
         
$vocabID = $v->vid;
          break;
        }
      }

     
// ensure vocabID exists
     
if (!$vocabID) return $block;

     
// get vocab term tree
     
$tree = taxonomy_get_tree($vocabID);

     
// loop through tree and collect term IDs
     
$termIDs = array();
      foreach (
$tree as $k => $v) {
       
$termIDs[$v->tid] = $v->name;
      }

     
// loop through term IDs and create views html
     
foreach ($termIDs as $k => $v) {

       
// get view object
       
$view = views_get_view($viewName); 

       
// ensure result is an object
       
if (!is_object($view)) continue;

       
// create view html
       
$viewHtml = views_build_view('block', $view, array($k), FALSE, $view->nodes_per_block);

        if (
strlen($viewHtml)) {
         
// show the taxonomy term name in an <h3>
         
$block_content .= "<h3>$v</h3>";

         
// add the view html to the block
         
$block_content .= $viewHtml;
        }

      }

     
$block['content'] = $block_content;
      return
$block;
      break;
  }
 
}
?>

The result will resemble the following structure...

Taxonomy Term 1
[node] [node] [node]

Taxonomy Term 2
[node] [node] [node]

Taxonomy Term 3
[node] [node] [node]

Here is how you can create a block view that shows related content items based on taxonomy. First, setup taxonomy for your node types. In my example, I created a category named 'Topics' and added a bunch of terms to it. Next, I edit/added my nodes and assigned taxonomy to them of this category.

Second, create a block view. Make sure you enter all the necessary information (filters, fields, sort criteria, etc). The piece that makes this view work is the argument. Add an argument of type "Taxonomy: Term ID". Change the option to "use empty text". I then assigned this block to a region and set it to only show up on certain node pages.

The next part involves adding some code. In my example, I needed to modify the html/css/layout of the block, so I decided to add a file to my theme called "block-views-MYVIEWNAME.tpl.php". This could have been accomplished using argument handling code (in the view settings), but I prefer to keep my code out of my database when possible, to version my code using subversion. Here's the contents of the block-views-MYVIEWNAME.tpl.php file...

<?php
// get node id from query string
if (substr($_REQUEST['q'], 0, 5)=='node/') {
 
$nodeID = substr($_REQUEST['q'], 5);   
} else {
 
$nodeID = substr(drupal_lookup_path('source', $_REQUEST['q']), 5);
}

// ensure the nodeID exists
if (!is_numeric($nodeID) || !$nodeID) return;

// load node object
$node = node_load($nodeID);

// ensure the node object was loaded
if (!is_object($node)) return;

// get vocabularies for this node
$vocabs = taxonomy_get_vocabularies($node->type);
   
// ensure there is taxonomy
if (!is_array($vocabs)) return;
if (
count($vocabs)==0) return;
   
// loop through vocablularies, look for vid that matches vocab name
foreach ($vocabs as $vocab) {
  if (
$vocab->name == 'Topics') {
   
$vid = $vocab->vid;
    break;
  }
}
   
// lookup terms for this node, by vocabularyID
$nodeTerms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vid);
   
// loop through node terms and get a list of term IDs
$nodeTermIDs = array();
foreach (
$nodeTerms as $nodeTerm) {
 
$nodeTermIDs[] = $nodeTerm->tid;
}
   
$args = $nodeTermIDs;

if (
count($args)==0) return;

// get view object
$view = views_get_view('related_content');

if (!
is_object($view)) return;

// generate view html
$viewHtml = views_build_view('block', $view, $args, FALSE, $view->nodes_per_block);

if (
$view->block_title && $viewHtml) echo "<h2>" . $view->block_title . "</h2>";
echo
$viewHtml;
?>

Here is how you can customize your theme (page.tpl.php) based on a node's taxonomy. First, I created a taxonomy vocabulary called "Page Layout" and assigned to terms to it: Wide and Narrow. I set the vocabulary's hierarchy to be disabled and multiple select is disabled. I then placed this code in my page.tpl.php, but can reside in node.tpl.php (or essentially anywhere that has access to the $node global).

<?php
$vocabName
= 'Page Layout';

// get vocabularies for this node
$vocabs = taxonomy_get_vocabularies($node->type);

// loop through vocablularies, look for vid that matches vocab name
foreach ($vocabs as $vocab) {
  if (
$vocab->name == $vocabName) {
   
$vid = $vocab->vid;
    break;
  }
}

// lookup terms for this node, by vocabularyID
$nodeTerms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vid);

// loop through node terms
foreach ($nodeTerms as $nodeTerm) {
  if (
$nodeTerm->vid == $vid) {
   
$cssClass = $nodeTerm->name;
    break;
  }
}
?>

Then, I can use the $className variable in my layout and theming. For instance...

<?php
print "<div class='$cssClass' />";
?>

...or like this...

<?php
switch ($cssClass) {
  case
'Wide':
   
// ...code...
   
break;
  case
'Narrow':
   
// ...code...
   
break;
}
?>

Syndicate content