[Note: An alternative method using template.php can be found here: http://drupal.org/node/133223 ]

I figured out a way to sort term links by vocab - this actually works (!) in node.tpl.php 465 (that's only for phphtemplate themes). It does look a bit clumsy - If anyone can tidy it up a bit I'd be very grateful. It probably belongs in the template.php really ... but I'm happy to just have it working at all!

What it does is create a new set of links for each vocab group of terms rather than just having all terms in a single row. eg the code below would produce something like:

# Submitted by: JohnG on 08 Mar 2006
# Forums: newbies - hacking - drupal
# Articles: contributed - in good faith - GPL

Please note, that the code below only processes terms for a single vocab each time - in the example (vid) 27 and 28. You need to replace all the occurrances of 27 with the vid of your favourite vocab.

You can copy&paste these code-chunks as often as you like to cover all your vocabs if you like, as long as you remember to edit all the '27's correctly it will work.

One more thing, I put all instances of this vocab filter script between the <?php if ($terms): ?> ... <?php endif; ?> tags and it works happily.

so it goes something like:

<?php if ($terms): ?>
<?php /* sort taxonomy links by vocabulary 27 */
$terms27 = taxonomy_node_get_terms_by_vocabulary($node->nid, 27);
 if ($terms27) {
  print '<div class="terms">Forums: ';
     foreach ($terms27 as $key => $term27) {
     $lterm27 = l($term27->name, 'taxonomy/term/'.$term27->tid);
  print $lterm27.' - ';
     }
  print '</div>';
 }
?>
<?php /* sort taxonomy links by vocabulary 28 */
$terms28 = taxonomy_node_get_terms_by_vocabulary($node->nid, 28);
 if ($terms28) {
  print '<div class="terms">Articles: ';
     foreach ($terms28 as $key => $term28) {
     $lterm28 = l($term28->name, 'taxonomy/term/'.$term28->tid);
  print $lterm28.' - ';
     }
  print '</div>';
 }
?>

repeat for each vocab vid as needed and then close the if ($terms): thingamy:

<?php endif; ?>

enjoy!

Comments

_-dave-_’s picture

If you want a more generic version of this the following code will loop through all vocabularies and output the related terms:

      <?php if ($terms): ?>
        <?php
          $vocabularies = taxonomy_get_vocabularies();
          foreach($vocabularies as $vocabulary) {
            if ($vocabularies) {
              $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vocabulary->vid);
              if ($terms) {
                print '<div class="terms"><h1>' . $vocabulary->name . ':</h1> ';
                foreach ($terms as $term) {
                  print l($term->name, 'taxonomy/term/'.$term->tid) . ' ';
                }
                print '</div>';
              }
            }
          }
        ?>
      <?php endif; ?>

Cheers
Dave

mariuss’s picture

Thanks a lot for this code, I was looking exactly for this :-)

I made one single change. Normally categories will add the term description as a tooltip (title attribute), and the code above is not doing this. Just add one more parameter to the function that creates the link:

...
print l($term->name, 'taxonomy/term/'.$term->tid, array('title' => $term->description) ) . ' '; 
...
GC_Chi’s picture

This is also exactly what I was looking for! Thank you!

Would it be possible to separate the multiple terms under the same vocab with a comma or straight bracket? Can you tweak the snippet? I would greatly appreciate it.

_-dave-_’s picture

If you haven't sorted this yet here is the code to add a comma - for a straight bracket change the comma on line that reads:

print l($term->name, 'taxonomy/term/'.$term->tid) . ', ';


if ($terms):

          $vocabularies = taxonomy_get_vocabularies();
          foreach($vocabularies as $vocabulary) {
            if ($vocabularies) {
              $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vocabulary->vid);
              if ($terms) {
                print '<div class="terms"><h1>' . $vocabulary->name . ':</h1> ';
                foreach ($terms as $term) {
                  print l($term->name, 'taxonomy/term/'.$term->tid) . ', ';
                }
                print '</div>';
              }
            }
          }
        

endif;

rondev’s picture

I just added a trim to remove the last separation:

  <?php
  $vocabularies = taxonomy_get_vocabularies();
  foreach($vocabularies as $vocabulary) {
    if ($vocabularies) {
      $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vocabulary->vid);
      $termslist = '';
      if ($terms) {
        print '<div class="terms">' . $vocabulary->name . ': ';
        foreach ($terms as $term) {
          $termslist = $termslist.l($term->name, 'taxonomy/term/'.$term->tid) . ' | ';
        }
      print trim ($termslist," |").'</div>';
      }

    }
  }
  ?>

And you can use the code at /node/38768 to get a solution for alpha sorting.

rondev’s picture

Now I use t() for terms too:

	<?php
		$vid = 5; /* vocabulaire 5 = Fruits */
		$result = db_query("SELECT t.tid, t.name FROM {term_data} t, {term_node} r WHERE r.tid = t.tid AND r.nid = %d AND t.vid = %d ORDER BY weight, name", array($node->nid, $vid));
		while ($term = db_fetch_object($result)) {
			$tags[] = l(t($term->name), 'taxonomy/term/' . $term->tid);
			}
		if ($tags) {
			print t("Products") . ": " . implode(' | ', $tags);
		}
	?>			
JuliaKM’s picture

I modified the code to use taxonomy_term_path. This is for vocabularies 1 and 2:

$terms = taxonomy_node_get_terms_by_vocabulary($node->nid, 1);
foreach ($terms as $term) {
  $tags[] = l($term->name, taxonomy_term_path($term));
	}
 print t("Vocab 1 Terms") . ": " . implode(' | ', $tags);


$terms = taxonomy_node_get_terms_by_vocabulary($node->nid, 2);
foreach ($terms as $term) {
  $tagsTwo[] = l($term->name, taxonomy_term_path($term));
	}
 print t("Vocab 2 Terms") . ": " . implode(' | ', $tagsTwo);

rondev’s picture

To sort alphabetically terms for i18n sites, I just tried to apply asort to the $tags array. I then needn't anymore of my previous use of db_query(). It works but not when l() is used. The following code then doesn't display hyperlinks of terms, it just displays the terms as text.
The following sample if for the vocabulary 5.

		$vid = 5; /* vocabulaire 5 = Fruits */
		$terms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vid);
		foreach ($terms as $term) {
			$tags[] =  t($term->name) ;
			}
		if ($tags) {
			asort($tags);
			print t("Products") . ": " . implode(' | ', $tags);
			}

I don't know how to sort $tag if
$tags[] = l(t($term->name), taxonomy_term_path($term));

Ronan

harmonyhalo’s picture

Hi there,
If you're using "t" for terms how then do you also print out the term description as above?

I'm trying to print out the term used within a vocabulary on a cck node , but also include the term description.
Thanks for any help (i'm a tragic php dunce)
-d

marcvangend’s picture

Thanks all, this is a very useful snippet. I made a small change, for those who care about the semantic web: I put the results in a definition list. My code:

<dl class="taxonomy">
<?php
$vocabularies = taxonomy_get_vocabularies();
foreach($vocabularies as $vocabulary) {
  if ($vocabularies) {
    $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vocabulary->vid);
    $termslist = '';
    if ($terms) {
      print '<dt class="vocabulary-name">' . $vocabulary->name . ':</dt><div class="vocabulary-terms">';
      foreach ($terms as $term) {
        print '<dd class="term-name">'.l($term->name, 'taxonomy/term/'.$term->tid) . '</dd>';
      }
      print '</div>';
    }

  }
}
?>
</dl>
demenece’s picture

Hi All, i've been based on this code to add the vocabulary name as a class to an unordered list of taxonomy items. This way you can later customize with CSS the style each taxonomy item will have depending on the vocabulary they belong.

- I've deleted the separator
- the unordered list tags (ul and li) add semantics to the code.
- I think it's easy to do (i'm not a php or drupal expert) and it should be in core, adding extra class to all elements will help a lot Drupal to be more popular for web designers!.

-I've put this in the taxonomy section of node.tpl.php from the Zen theme, not sure if this is the best way to do it.

<?php if (count($taxonomy)):
          $vocabularies = taxonomy_get_vocabularies();
		  print '<ul class="taxonomy-section">';
          foreach($vocabularies as $vocabulary) {
            if ($vocabularies) {
              $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vocabulary->vid);
              if ($terms) {
                print '<li class="taxonomy ' . $vocabulary->name . '">';
                foreach ($terms as $term) {
                  print l($term->name, 'taxonomy/term/'.$term->tid);
                }
                print '</li>';
              }
            }
          }
		  print '</ul> <!-- /taxonomy-section -->';
	endif; ?>

Here you have an screenshot of what you can do with this and a little of CSS

And here is the CSS beyond it (not yet ready for IE):

.taxonomy-section{
	padding:0;
	font-size:9pt;
	list-style-type:none;
	clear:both;}
.taxonomy-section li{
	float:left;
	margin:0;}
.taxonomy a{
	padding:5px;
	padding-left:20px;
	margin-bottom:30px;
	margin-right:3px;
	border: solid 1px #85be94;
	border-left-width:5px;
	color:#333333;
	text-decoration:none;
	background: url(images/tag_green.png) #a5deb4 2px 6px no-repeat;}
.node-type-product .taxonomy a:hover{
	background-color:#85be94;}
.node-type-product .linea a{
	background: url(images/tag_yellow.png) #f9f7e6 2px 6px no-repeat;
	border-color:#ffff99;}
.node-type-product .linea a:hover{
	background-color:#ffff99;}
.node-type-product .linea a:before{
	content:"en la linea ";
	color:#666666;}
.node-type-product .General a:before{
	content:"categoria ";
	color:#666666;}

icons belong to the Silk pack created by famfamfam

mooffie’s picture

$vocabularies = taxonomy_get_vocabularies();
[...]
$terms = taxonomy_node_get_terms_by_vocabulary(...);

Just to let you know: these add extra SQL queries to your page (they are not cached).

And instead of:

 l($term->name, 'taxonomy/term/'.$term->tid, ...)

Better use:

l($term->name, taxonomy_term_path($term->tid), ...)

(So that 'forum.module' and 'image_gallery.module' and lots other can specialize the link.)

conniec’s picture

HI all,

I need to add a specific div class to each vocabulary, so I came up with this variation (see the print statements):

 if (count($taxonomy)):
          $vocabularies = taxonomy_get_vocabularies();
                 foreach($vocabularies as $vocabulary) {
            if ($vocabularies) {
		   $terms = taxonomy_node_get_terms_by_vocabulary($node, $vocabulary->vid);
			$vocab = $vocabulary->name;
			$termlist = '';
              if ($terms) {
                print '<div class= "'; 
				print $vocab;
				print '">' . $vocabulary->name . ': ';
                foreach ($terms as $term) {
				$termlist = $termlist.l($term->name, taxonomy_term_path($term->tid) . ', ');
                
                print trim($termlist, ", ").'</div>';
              }
            }
          }
		}
          print '<!-- /end of terms -->';
    endif; 

So now my

prints out with the actual vocabulary term; which means that each vocabulary can be styled differently. Yea!
ie
I have three vocabularies: oranges, pears and apples.
Splitting up the print functions lets me print out this:
Oranges:
Pears:
Apples:

With my small php skills, this took me a while to figure out, so I'm posting to save someone else some time.

Connie

lias’s picture

Thanks ConnieC, this worked great to display vocabularies on separate lines. One question, how can you separate the terms with a comma or other symbol using this code?

actually comment http://drupal.org/node/53089#comment-1493216 worked this all out.

stanbroughl’s picture

connie, if it was possible to jump through a computer, my arms would be latched around you! this is perfect for something i've been scratching my head over. THANK YOU!

bartezzini’s picture

Is there anyway do update this to work with drupal6 too?
Thx

Jeff Burnz’s picture

Works for me in D6...

if ($terms):
// replace '4' with your vocabulary ID
$terms = taxonomy_node_get_terms_by_vocabulary($node, 4);
if ($terms) {
     foreach ($terms as $key => $term) {
     $items[] = l($term->name, taxonomy_term_path($term), array('attributes' => array('rel' => 'tag', 'title' => $term->description)));
     }
	 print '<p>' . t("Filed in: ") . implode(', ', $items) . '</p>';
	 // alternativle comment out the above and uncomment the following to theme as an item list.
	 //print theme('item_list', $items);
}
endif;
bartezzini’s picture

I got a problem with this snippet:
I got 2 taxonomy term, with this snippet when I print the first one (number 1) everything is ok; but in the second call (taxomony term nr2) I have all the terms (taxonomy 1+2) and not the taxonomy 2 alone.
Any suggestion?

Jeff Burnz’s picture

Arr, I see, yes me so lazy, sorry... wipped that out a bit too fast by the l@@ks..

See the "$items" bit, add the vocab id to it and it should solve your problem... i.e...

if (count($taxonomy)):
// replace '4' with your vocabulary ID
$terms = taxonomy_node_get_terms_by_vocabulary($node, 4);
if ($terms) {
     foreach ($terms as $key => $term) {
     $items4[] = l($term->name, taxonomy_term_path($term), array('attributes' => array('rel' => 'tag', 'title' => $term->description)));
     }
     print '<p>' . t("Filed in: ") . implode(', ', $items4) . '</p>';
     // alternatively theme as an item list.
     //print theme('item_list', $items4);
}
endif;
Summit’s picture

Subscribing,

any solution for not doing a database-query on D5?

$vocabularies = taxonomy_get_vocabularies();
[...]
$terms = taxonomy_node_get_terms_by_vocabulary(...);

greetings, Martijn

alienresident’s picture

I have tried many examples to sort my terms alphabetically from one vocabulary and print them on my node.

Below is the solution that worked for me.

http://drupal.org/node/133223#comment-634019

I believe the difference is that this version is calling the node's taxonomy which is already sorted alphabetically rather than calling all the terms that are associated with the node which seems to default to sorting by the term id (tid) or weight rather than the term name.

taxonomy_node_get_terms_by_vocabulary — gets the terms but orders them by weight then tid.

where as
$node->taxonomy gets the terms from the node without ordering by weight or tid

Please let me know if my assumptions are wrong.

Hopefully this will help others.

Turkish Delight’s picture

I'd like to print out terms from one vocabulary in an orderly manner which this snippet more than does, however if I add a php print $terms anywhere after (and only after, if I use the standard php print $terms beforehand everything works alright) this snippet the output is "array". Do you or does anyone know why this is? I would like to have terms from other vocabularies printed underneath the vocabulary that comes out orderly.

Turkish Delight’s picture

I've put this snippet into my node.tpl.php, and oddly enough it works for one term and its subterms, but for other terms and its subterms they are displayed backwards (subterm 3 << subterm 2 << subterm 1 << term). The hierarchy is still accurate (ie if I were to click on subterm 1 it would be recognized as subterm 1 and not subterm 3) so I know it is not an error on the part of the taxonomy module.

theJT’s picture

I'm using a very cut down version of this in an attempt to perform some theming on my site. In one instance I've got:

background: url(../sites/all/files/img/<?php
if ($terms):
$terms = taxonomy_node_get_terms_by_vocabulary($node, 4);
if ($terms) {
       foreach ($terms as $term) {
          print $term->name; }
}
endif;
?>.png;

happily printing the name of a vocab term into a little bit of inline styling in node.tpl.php and it works perfectly.

I thought I could use the same code to perform a similar trick in a user created block to insert an image based on the page's vocabulary terms... but it doesn't work there.

in that case I have

<img src="../sites/all/files/img/<?php
if ($terms):
$terms = taxonomy_node_get_terms_by_vocabulary($node, 4);
if ($terms) {
       foreach ($terms as $term) {
          print $term->name; }
}
endif;
?>.png" alt="some image">

but the image doesn't show, only the alt text. Checking the page source in firefox shows that it's printing

<img src="../sites/all/files/img/.png" alt="some image">

...which obviously doesn't exist. It seems the PHP is simply being ignored, despite the block source being set as php code in the input format area.

more basic php such as

<?php print "Is this working?" ?>

is printed fine.

I presume the problem is that the variables I'm trying to call are just meaningless in this context, but I'm pretty new to drupal and PHP so I'm not sure where those variables are being defined or under what circumstances I'm allowed to call them. Any pointers would be most gratefully recieved.

marcvangend’s picture

theJT,
This page (a documentation page in the theming guide) is a place to share working code, not a place to request individual support. Please:
- post your question on the forum
- ask a site maintainer (http://drupal.org/node/add/project-issue/webmasters) to remove both your comment and this one

nsyll’s picture

Step one
Add the following snippet to your template.php file:

function yourthemename_get_terms_by_vocabulary($node, $vid, $label = 0) {
  $terms = taxonomy_node_get_terms_by_vocabulary($node, $vid);
  if ($terms) {
    $links = array();
    if ($label != 0) { 
      $output = '<div class="term vid-' .$vid .'">' .$label .': '; 
    }
    else {
      $vocabulary = taxonomy_vocabulary_load($vid);
      //print_r($vocabulary);
      //exit();
      $output .= '<div class="term vid-' .$vid .'">' .$vocabulary->name .': ';
    }
    foreach ($terms as $term) {
      $links[] = l($term->name, taxonomy_term_path($term), array('rel' => 'tag', 'title' => strip_tags($term->description)));
    }
    $output .= implode(', ', $links);
    $output .= '</div>';
  }
    
  return $output;  
}

Step two

Now add the following to your node.tpl.php file:
if the vocabulary has vid 1

<?php
print yourthemename_print_terms($node, 1)
?>

if you want custom label

<?php
print yourthemename_print_terms($node, 1, "story tags")
?>

Have fun!!

sdemircan’s picture

hi for me don't work in you node.tpl.php you say if you add print yourthemename_print_terms($node, '$vid'); but i don't have a function yourthemename_print_terms ?? how do you make?

marcvangend’s picture

Read the documentation about theme overides, it is important to understand how they work. Once you understand theme overrides, you will have learned that in the code above, "yourthemename" should by replaced by the name of your theme.

alphex’s picture

You say to use "yourthemename_print_terms($node, 1)"

When it should be the same as your function name in template.php

"yourthemename_get_terms_by_vocabulary(...)"

] duran goodyear
] alphex information solutions, llc.
] http://alphex.com

halloffame’s picture

I second to this. Function name should be the same.

asanchez75’s picture

if ($terms):

          $vocabularies = taxonomy_get_vocabularies();
          foreach($vocabularies as $vocabulary) {
            if ($vocabularies) {
              $terms = taxonomy_node_get_terms_by_vocabulary($node, $vocabulary->vid);
              if ($terms) {
                print '<div class="terms"><h1>' . $vocabulary->name . ':</h1> ';
                foreach ($terms as $term) {
                  print l($term->name, 'taxonomy/term/'.$term->tid) . ' ';
                }
                print '</div>';
              }
            }
          }
        

endif;

I changed $node->vid parameter by $node parameter because must be a object for D6 (see http://tinyurl.com/3ypdyfa).

stanbroughl’s picture

someone delete my error?