To show a block only for an specific taxonomy term, here is how to do it:

<?php
  $myterm = 163; // replace this id with the term id you want to use.
  // This will show on all nodes having this term
  if ((arg(0) == 'node') && is_numeric(arg(1))) {
    $terms = taxonomy_node_get_terms(arg(1));
    foreach($terms as $term) {
      if ($term->tid == $myterm) return TRUE;
    }
  }
  // This will show on the index page for that term
  if ((arg(0) == 'taxonomy') && (arg(1) == 'term') && (arg(2) == $myterm)) {
    return TRUE;
  }
  // Otherwise
  return FALSE;
?>

To do the same for more than one taxonomy term use in_array() instead:

<?php
  $myterms = array(8, 9, 12, 21); // list the ids of the terms you want
  // This will show on all nodes having this term
  if ((arg(0) == 'node') && is_numeric(arg(1))) {
    $terms = taxonomy_node_get_terms(arg(1));
    foreach($terms as $term) {
      if (in_array($term->tid, $myterms)) return TRUE;
    }
  }
  // This will show on the index page for that term
  if ((arg(0) == 'taxonomy') && (arg(1) == 'term') && (in_array(arg(2), $myterms))) {
    return TRUE;
  }
  // Otherwise
  return FALSE;
?>

Enjoy!

Comments

gragus’s picture

In Dripal 6.2 the parameter to the function taxonomy_node_get_terms() is not a node ID, but an object.
Yestarday was my first day using Drupal and I spent several hours figuring that out.
My solution is based on the code available here: http://api.drupal.org/api/function/taxonomy_node_get_terms_by_vocabulary/6
That function is very simular to the one used above (http://api.drupal.org/api/function/taxonomy_node_get_terms/6) and
I am only using the former in order to be slightly more efficient as I already know both - the term and vocabulary IDs. You can adjust the code below if you do not know the vocabulary ID in your case.

Note, this function is executed during every page load. For efficiency reasons I have copied the SQL statement from taxonomy_node_get_terms_by_vocabulary() directly into my own code. This often saves traversing the while loop too many times, but is bad style and you should not do it if you have enough computing power.
By code is:

<?php
$tid = 1; // vocabulary term ID for whivh to display the block
$vid = 1; // Vocablulary ID (We ignore all but one vocabularies for speed)
if (arg(0) == 'node' && is_numeric(arg(1))) {
    $nid = arg(1);
    $r = db_query(db_rewrite_sql('SELECT t.tid, t.* FROM {term_data} t INNER JOIN {term_node} r ON r.tid = t.tid WHERE t.vid = %d AND r.vid = %d ORDER BY weight', 't', 'tid'), $vid, $nid);
	while ($term = db_fetch_object($r)) {
		if ($term->tid == $tid)
			return TRUE;
	}
}
return FALSE;
?>
gragus’s picture

Reg. my previous post (http://drupal.org/node/113651#comment-841679):

In opposite to the examples in the main post it does not show the block on index pages for the term in question - this was intended.
Here is an extended version. It shows a block when the current node belongs to a taxonomy category with the ID $displayTermID or any of the sub-categories of that category. For instance if you have a taxonomy like:

Windows
- Windows 95
- Windows XP
Linux
- SuSE
- Debian

and you want to display a block on all nodes that belong to all sub-categories of Windows (i.e. "Windows", "Windows 95", "Windows XP") you can use this approach. $displayTermID must be the ID of "Windows".

Note, today is my second day of using Drupal, so I apologise if something is wrong, but I think that this version uses the Drupal 6.2 API correctly.

<?php

// Vocabulary term ID for which to display the block:
$displayTermID = 1; 

// If current node is not a normal node, then fail-fast:
if (arg(0) != 'node' || !is_numeric(arg(1))) {
	// echo "<p>Will return FALSE1.</p>";
	return FALSE;
}

// Get all taxonomy terms for current node:
$currNode = new stdClass();
$currNode->vid = arg(1);
$currNodeTerms = taxonomy_node_get_terms($currNode);

// If there are no terms, fail-fast:
if (is_null($currNodeTerms) || 0 == count($currNodeTerms)) {
	// echo "<p>Will return FALSE2.</p>";
	return FALSE;
}

// For each term of the current node, get all the ancestor terms:
foreach($currNodeTerms as $term) {
	$ancestors = taxonomy_get_parents_all($term->tid);
		
	// Chech for each ancestor term whether is is the term we are looking for.
	// If it is, return TRUE immediately:
	if (!is_null($ancestors) && 0 < count($ancestors)) {
		foreach($ancestors as $ancestor) {
			if ($displayTermID == $ancestor->tid) {
				// echo "<p>Will return TRUE.</p>";
				return TRUE;
			}
		}
	}
}

// If we didn't find our term of interest, return FALSE:
// echo "<p>Will return FALSE3.</p>";
return FALSE;
?>
rout’s picture

as you indicated, but not on the taxonomy index listing page.

Here is a suggestion on how to get this to show the block on the index page as well:

<?php

// Vocabulary term ID for which to display the block:
$displayTermID = 4;

// This will show on the index page for that term
  if ((arg(0) == 'taxonomy') && (arg(1) == 'term') && (arg(2) == $displayTermID)) {
    return TRUE;
  }

// Get all taxonomy terms for current node:
$currNode = new stdClass();
$currNode->vid = arg(1);
$currNodeTerms = taxonomy_node_get_terms($currNode);

// If there are no terms, fail-fast:
if (is_null($currNodeTerms) || 0 == count($currNodeTerms)) {
    // echo "<p>Will return FALSE2.</p>";
    return FALSE;
}

// For each term of the current node, get all the ancestor terms:
foreach($currNodeTerms as $term) {
    $ancestors = taxonomy_get_parents_all($term->tid);
       
    // Chech for each ancestor term whether is is the term we are looking for.
    // If it is, return TRUE immediately:
    if (!is_null($ancestors) && 0 < count($ancestors)) {
        foreach($ancestors as $ancestor) {
            if ($displayTermID == $ancestor->tid) {
                // echo "<p>Will return TRUE.</p>";
                return TRUE;
            }  
        }
    }
}


// If we didn't find our term of interest, return FALSE:
// echo "<p>Will return FALSE3.</p>";
return FALSE;
?>
rout’s picture

Can anyone assist in modifying this snippet so that blocks will show on all sub-term index pages, as well as that of the root ancestor?

gragus’s picture

Hi,

not sure what you mean by "so that blocks will show on all sub-term index pages, as well as that of the root ancestor". Your code (I think, I have not tried it) should show the block in the following cases:
- When a node is displayed that has a category term with the ID $displayTermID assigned to it.
- When a node is displayed that has a category term T assigned to it, such that T has an ancestor term with the ID $displayTermID.
- When a category listing for the term with the ID $displayTermID is displayed.

I think, what you want is to also display the block when a category listing for a term is displayed that has an ancestor with the ID $displayTermID. I have removed the Drupal 6 installation and replaced it with it with Drupal 5.7 because of the serious lack of modules for Drupal 6 makes is not very useful for me (e.g. see discussion at http://drupal.org/node/259586, but that is unrelated). Because of this I cannot really show you a WORKING Drupal 6 snippet here, but here is what you need to do in general:


/*
Note, I have written this directly into the Drupal forum text box.
I have not tested this code, as I am now using a different Drupal version, so it is likely to contain bugs.
This code is just supposed to give an idea of how to proceded.
*/

// Fetch an array of currently displaying taxonomy terms according to the current display:
if (arg(0) == 'node' && is_numeric(arg(1))) {
    // Get all taxonomy terms for current node:
    $currNode = new stdClass();
    $currNode->vid = arg(1);
    $currNodeTerms = taxonomy_node_get_terms($currNode);

} else if ((arg(0) == 'taxonomy') && (arg(1) == 'term') && is_numeric(arg(2)) {
    // The current term is the one being listed:
    // (note, you need to adjust this if you want to process listings of several category terms)
    $currNodeTerms =array();
    $term = new stdClass();
    $term->tid = arg(2);
    $currNodeTerms[] = $term;
} else {
    return FALSE;
}

// If there are no terms, fail-fast:
if (is_null($currNodeTerms) || 0 == count($currNodeTerms)) {
    return FALSE;
}

// For each term of the current node, get all the ancestor terms:
foreach($currNodeTerms as $term) {
    $ancestors = taxonomy_get_parents_all($term->tid);
      
    // Check for each ancestor term whether is is the term we are looking for.
    // If it is, return TRUE immediately:
    if (!is_null($ancestors) && 0 < count($ancestors)) {
        foreach($ancestors as $ancestor) {
            if ($displayTermID == $ancestor->tid)
                return TRUE;
        }
    }
}


// If we didn't find our term of interest, return FALSE:
return FALSE;
Rowanw’s picture

I tried the code above but it didn't work, the code below should work though.

<?php

// Vocabulary term ID for which to display the block:
$displayTermID = 6;

// This will show on the index page for that term
  if ((arg(0) == 'taxonomy') && (arg(1) == 'term') && (arg(2) == $displayTermID)) {
    return TRUE;
  }

$ancestors = taxonomy_get_parents_all(arg(2));
      
// Check for each ancestor term whether it is the term we are looking for.
// If it is, return TRUE immediately:
if (!is_null($ancestors) && 0 < count($ancestors)) {
    foreach($ancestors as $ancestor) {
        if ($displayTermID == $ancestor->tid) {
            // echo "<p>Will return TRUE.</p>";
            return TRUE;
        }
    }
}

// Get all taxonomy terms for current node:
$currNode = new stdClass();
$currNode->vid = arg(1);
$currNodeTerms = taxonomy_node_get_terms($currNode);

// If there are no terms, fail-fast:
if (is_null($currNodeTerms) || 0 == count($currNodeTerms)) {
    // echo "<p>Will return FALSE2.</p>";
    return FALSE;
}

// For each term of the current node, get all the ancestor terms:
foreach($currNodeTerms as $term) {
    $ancestors = taxonomy_get_parents_all($term->tid);
      
    // Check for each ancestor term whether it is the term we are looking for.
    // If it is, return TRUE immediately:
    if (!is_null($ancestors) && 0 < count($ancestors)) {
        foreach($ancestors as $ancestor) {
            if ($displayTermID == $ancestor->tid) {
                // echo "<p>Will return TRUE.</p>";
                return TRUE;
            } 
        }
    }
}

// If we didn't find our term of interest, return FALSE:
// echo "<p>Will return FALSE3.</p>";
return FALSE;
?>

--
How to override HTML in Drupal 6

sebos69’s picture

Hi, and thank you for the small examples. Unfortunately, they did not work on my install. Here is a version which worked for me:

<?php
if ( arg(0) == 'node' and is_numeric(arg(1)) and arg(2) == FALSE ) {

// Vocabulary term ID for which to display the block:
$displayTermID =1;
     
// Get all taxonomy terms for current node:
$currNodeTerms = taxonomy_node_get_terms(node_load(arg(1)));

// If there are no terms, fail-fast:

if (is_null($currNodeTerms) || 0 == count($currNodeTerms)) {
    return FALSE;
}

// For each term of the current node, get all the ancestor terms:
foreach($currNodeTerms as $term) {

    $ancestors = taxonomy_get_parents_all($term->tid);
     
    // Check for each ancestor term whether it is the term we are looking for.
    // If it is, return TRUE immediately:
    if (!is_null($ancestors) && 0 < count($ancestors)) {
        foreach($ancestors as $ancestor) {
            if ($displayTermID == $ancestor->tid) {
                return TRUE;
            }
        }
    }
}
}
// If we didn't find our term of interest, return FALSE:
return FALSE;
?>

basically, the difference with prior art is:

$currNodeTerms = taxonomy_node_get_terms(node_load(arg(1)));
federico’s picture

In my case, this code show the block on every node page, but not on the taxonomy lists or index pages for the term in question. I tried also removing if ( arg(0) == 'node' and is_numeric(arg(1)) and arg(2) == FALSE ) but still had no success.

But this worked for me:

<?php


// Vocabulary term ID for which to display the block:
$displayTermID =123;

// This will show on the index page for that term
  if ((arg(0) == 'taxonomy') && (arg(1) == 'term') && (arg(2) == $displayTermID)) {
    return TRUE;
  }

// Get all taxonomy terms for current node:
$currNodeTerms = taxonomy_node_get_terms(node_load(arg(1)));

// If there are no terms, fail-fast:

if (is_null($currNodeTerms) || 0 == count($currNodeTerms)) {
    return FALSE;
}

// For each term of the current node, get all the ancestor terms:
foreach($currNodeTerms as $term) {

    $ancestors = taxonomy_get_parents_all($term->tid);
    
    // Check for each ancestor term whether it is the term we are looking for.
    // If it is, return TRUE immediately:
    if (!is_null($ancestors) && 0 < count($ancestors)) {
        foreach($ancestors as $ancestor) {
            if ($displayTermID == $ancestor->tid) {
                return TRUE;
            }
        }
    }
}

// If we didn't find our term of interest, return FALSE:
return FALSE;
?>

One issue is that the block is not show on index pages for terms that are subterms (child terms) of the term in question.

Thanks for your help.