Create comma-separated taxonomy term list in Drupal
I was wondering how to create a comma-separated taxonomy term list per node, because the default space-separated list is confusing for terms containing spaces (I only use a few but still). I temporarily solved it with CSS by adding a visual separation with a background image for all but the first terms. In honesty, it worked but it looked rather clunky.
/* Taxonomy terms */
.tags li {
background: transparent url(img/dot.png) no-repeat left center;
padding-left: 19px; /*leave any top/bottom padding*/
padding-right: 0px;
margin-left: 0px; /*leave any top/bottom margin*/
margin-right: 0px;
}
.tags li.first {
background: none !important;
padding-left: 0 !important;
}
Until I stumbled upon a 2008 post at Kobashi Computing in which the author accomplishes exactly what I was looking for.
<?php
function phptemplate_preprocess_node(&$vars) {
// Taxonomy hook to show comma-separated terms
if (module_exists('taxonomy')) {
$vars['term_links'] = '';
$count = 1;
$term_links = taxonomy_link('taxonomy terms', $vars['node']);
$numcount = count($term_links);
if ($numcount > 0) {
foreach ($term_links as $link_item) {
$vars['term_links'] .= l($link_item['title'], $link_item['href'], $link_item);
if ($count < $numcount)
$vars['term_links'] .= ', ';
$count++;
}
}
}
}
?>
Thanks for sharing this great code snippet.
In your node templates you can still test if there are taxonomy terms available for the node by using <?php if ($terms) { ... } ?>
and then instead of using <?php print $terms; ?>
you use the newly defined <?php print $term_links; ?>
.
Compacter solution
And then based on the code found at gerardmcgarry.com you could come up with the following code for the template.php
.
<?php
function phptemplate_preprocess_node(&$vars) {
// Taxonomy hook to show comma separated terms
if (module_exists('taxonomy')) {
$term_links = array();
foreach ($vars['node']->taxonomy as $term) {
$term_links[] = l($term->name, 'taxonomy/term/' . $term->tid,
array(
'attributes' => array(
'title' => $term->description
)));
}
$vars['node_terms'] = implode(', ', $term_links);
}
}
?>
I like the use of implode()
— see php.net for the syntax.
Just use <?php print $node_terms; ?>
in the node template to display the terms. Of course, test for the existence of terms first, like in the previous example.
<?php if ($terms) { ?>
<div class="tags">
<span><?php print t('Tags: '); ?></span><?php print $node_terms; ?>
</div>
<?php } ?>
Too bad that this is not optional in Drupal.
Comments
Just wanted to say thanks! I was having trouble with this, and your solution solved it.
I posted a solution to this problem some time ago on my Drupal Blog - http://oliverdavies.co.uk/2010/04/05/sty...
Is there any way of outputting the url links as lowercase, but keeping the printed list normal?
In other words:
Term name -> term name
Business -> business
Thus you would get a list of:
Business, Entertainment, Leisure
that has the url paths:
business, entertainment, leisure
Found my answer. Edit:
$term_links[] = l($term->name, 'category/' . $term->name,
to
$term_links[] = l($term->name, 'category/' . strtolower($term->name),
Thanks for taking the time to post your solution.
hi, thanks for the snippet. i'm struggling with a modification to this to allow display of links on a per-vocabulary basis, ala http://timonweb.com/how-to-separate-drupal-taxonomy-terms-output-by-vocabulary
can you offer any advice?
There is an easy example at Drupal: Display taxonomy terms broken out by vocabulary:
<?php
function yourthemename_print_terms($node, $vid = NULL, $ordered_list = TRUE) {
$vocabularies = taxonomy_get_vocabularies();
if ($ordered_list) $output .= '<ul>'; //checks to see if you want an ordered list
if ($vid) { //checks to see if you've passed a number with vid, prints just that vid
$output = '<div class="tags-'. $vid . '">';
foreach($vocabularies as $vocabulary) {
if ($vocabulary->vid == $vid) {
$terms = taxonomy_node_get_terms_by_vocabulary($node, $vocabulary->vid);
if ($terms) {
$links = array();
$output .= '<span class="only-vocabulary-'. $vocabulary->vid . '">';
if ($ordered_list) $output .= '<li class="vocabulary-'. $vocabulary->vid . '">' . $vocabulary->name . ': ';
foreach ($terms as $term) {
$links[] = '<span class="term-' . $term->tid . '">' . l($term->name, taxonomy_term_path($term), array('rel' => 'tag', 'title' => strip_tags($term->description))) .'</span>';
}
$output .= implode(', ', $links);
if ($ordered_list) $output .= '</li>';
$output .= '</span>';
}
}
}
}
else {
$output = '<div class="tags">';
foreach($vocabularies as $vocabulary) {
if ($vocabularies) {
$terms = taxonomy_node_get_terms_by_vocabulary($node, $vocabulary->vid);
if ($terms) {
$links = array();
$output .= '<ul class="vocabulary-'. $vocabulary->vid . '">';
if ($ordered_list) $output .= '<li class="vocabulary-'. $vocabulary->vid . '">' . $vocabulary->name . ': ';
foreach ($terms as $term) {
$links[] = '<span class="term-' . $term->tid . '">' . l($term->name, taxonomy_term_path($term), array('rel' => 'tag', 'title' => strip_tags($term->description))) .'</span>';
}
$output .= implode(', ', $links);
if ($ordered_list) $output .= '</li>';
$output .= '</ul>';
}
}
}
}
if ($ordered_list) $output .= '</ul>';
$output .= '</div>';
return $output;
}
?>
This code needs some cleaning up since it violates the Drupal coding standard but it does the job. As per the example:
template.php
and rename it to something suitable.<?php print yourthemename_print_terms($node, $vid = NULL, $unordered_list = TRUE); ?>
.It then returns the terms as a comma-separated list per vocabulary.
Works grate!
Thank you...
Works grate!
Thank you...
totally awesome !