display the last (x) nodes associated with a vocabulary
Last modified: July 12, 2008 - 08:02
NB. If using 5.x or later, the Views module provides this functionality (and much more) through the user interface. http://drupal.org/project/views
<?php
$limit = 5;
function get_nodes($tid, $limit) {
$result = db_query(db_rewrite_sql("SELECT node.title, node.nid, node.changed FROM node INNER JOIN term_node ON node.nid = term_node.nid WHERE term_node.tid = %d AND node.status = 1 AND node.moderate = 0 AND node.promote = 1 ORDER BY node.created DESC LIMIT %d"), $tid, $limit);
while ($anode = db_fetch_object($result)) {
$changed = date('m/j', $anode->changed);
$items[] = l($anode->title, "node/". $anode->nid) . " ($changed)";
}
if(!$items) {
return;
} else {
return theme_item_list($items);
}
}
$vid = 2;
$result = db_query("SELECT tid, name FROM {term_data} WHERE vid = %d", $vid);
while ($t = db_fetch_object($result)) {
$nodes = get_nodes($t->tid,$limit);
if ($nodes) {
print "<h3> $t->name </h3>";
print $nodes;
}
}
?>
Duplicate entries
Is there a way to avoid duplicate entries, such as when a node has more than one category in the vocabulary? At present, if the node has more than one category, it will show up once for each category ... how would I set it to show an article only for the first listed category?
http://www.machinehasnoagenda.com
Create an array of already displayed nodes
You could create an array of already displayed nodes. Here's an altered version of the above code. Notice the static variable $displayed_nodes and the optional parameter $unique.
<?php
function get_nodes($tid, $limit, $unique=false) {
static $displayed_nodes = array();
$result = db_query(db_rewrite_sql("SELECT node.title, node.nid, node.changed FROM node INNER JOIN term_node ON node.nid = term_node.nid WHERE term_node.tid = %d AND node.status = 1 AND node.moderate = 0 AND node.promote = 1 ORDER BY node.created DESC LIMIT %d"), $tid, $limit);
$items = array();
while($anode = db_fetch_object($result)) {
if($unique and in_array($anode->nid, $displayed_nodes))
continue;
$displayed_nodes[] = $anode->nid;
$changed = date('m/j', $anode->changed);
$items[] = l($anode->title, 'node/'.$anode->nid) . " ($changed)";
}
if(!empty($items))
return theme_item_list($items);
}
$vid = 2;
$result = db_query("SELECT tid, name FROM {term_data} WHERE vid = %d", $vid);
while($t = db_fetch_object($result)) {
$nodes = get_nodes($t->tid, $limit, true);
if($nodes) {
print "<h3> $t->name </h3>";
print $nodes;
}
}
?>
Efficient code (to avoid duplicate article listing)
<?php
$limit = 5;
function get_nodes($tid, $limit) {
$result = db_query(db_rewrite_sql("SELECT node.title, node.nid, node.changed FROM node INNER JOIN term_node ON node.nid = term_node.nid WHERE term_node.tid = %d AND node.status = 1 AND node.moderate = 0 AND node.promote = 1 ORDER BY node.created DESC LIMIT %d"), $tid, $limit);
while ($anode = db_fetch_object($result)) {
$changed = date('m/j', $anode->changed);
// added a key to array to avoid duplicate article listing when an article is associated with multiple categories -
$items[$anode->nid] = l($anode->title, "node/". $anode->nid) . " ($changed)";
}
if(!$items) {
return;
} else {
return theme_item_list($items);
}
}
$vid = 2;
$result = db_query("SELECT tid, name FROM {term_data} WHERE vid = %d", $vid);
while ($t = db_fetch_object($result)) {
$nodes = get_nodes($t->tid,$limit);
if ($nodes) {
print "<h3> $t->name </h3>";
print $nodes;
}
}
?>
Vinay Yadav
PHP / Drupal Specialist
http://www.vinayras.com
I had bad problems with this
I had bad problems with this code, relating to a few access control modules. Remove "db_rewrite_sql(" to make it work. If I'm right this makes no sense here, because it's only relevant for access control? Anyway, it could cause trouble.
Webshop software met iDeal
Another code to avoid replicated
the aboves codes seems not work to me in Drupal 5 so I adapted
<?php
$limit = 5;
$nodos_mostrados=array();
function get_nodes($tid, $limit, &$nodos_mostrados) {
$result = db_query(db_rewrite_sql("SELECT node.title, node.nid, node.changed FROM node INNER JOIN term_node ON node.nid = term_node.nid WHERE term_node.tid = %d AND node.status = 1 AND node.moderate = 0 AND node.promote = 1 ORDER BY node.created DESC LIMIT %d"), $tid, $limit);
while ($anode = db_fetch_object($result)) {
if (in_array ($anode->nid, $nodos_mostrados))
return;
else
{
$nodos_mostrados[]=$anode->nid;
$changed = date('m/j', $anode->changed);
$items[] = l($anode->title, "node/". $anode->nid) . " ($changed)";
}
if(!$items) {
return;
} else {
return theme_item_list($items);
}
}
}
$vid = 2; //Your Vocabulary
$result = db_query("SELECT tid, name FROM {term_data} WHERE vid = %d", $vid);
while ($t = db_fetch_object($result)) {
$nodes = get_nodes($t->tid,$limit, $nodos_mostrados);
if ($nodes) {
print "<h3> $t->name </h3>";
print $nodes;
}
}
?>
The idea is an array of showed nodes $nodos_mostrados where the function saves all the nodes to display and avoid every node that previously has showed.
NOTE: I have some problems with the db_rewrite_sql function that solves when I removed it. so you must change
$result = db_query(db_rewrite_sql("SELECT node.title, node.nid, node.changed FROM node INNER JOIN term_node ON node.nid = term_node.nid WHERE term_node.tid = %d AND node.status = 1 AND node.moderate = 0 AND node.promote = 1 ORDER BY node.created DESC LIMIT %d"), $tid, $limit);with
$result = db_query("SELECT node.title, node.nid, node.changed FROM node INNER JOIN term_node ON node.nid = term_node.nid WHERE term_node.tid = %d AND node.status = 1 AND node.moderate = 0 AND node.promote = 1 ORDER BY node.created DESC LIMIT %d", $tid, $limit);It's also working on Drupal 6
and for info,
don't insert this code several times without change the name of the function...
... eval error and your site will be down if you show the block.
In the same way, I corrected a small error in the previous post, because only one post was displayed.
I also changed a little bit the query to be less restrictive: if the node is published it's enough (I don't care about the moderate notion or if the article must be on the home page).
I also a little bit restructured the code: 2 functions, no global variables (in case of).
Here is the code
<?php
function get_nodes($tid, $limit, &$nodos_mostrados) {
$result = db_query(db_rewrite_sql("SELECT node.title, node.nid, node.changed
FROM node INNER JOIN term_node ON node.nid = term_node.nid
WHERE term_node.tid = %d AND node.status = 1
ORDER BY node.created DESC LIMIT %d"), $tid, $limit);
while ($anode = db_fetch_object($result)) {
if (!in_array ($anode->nid, $nodos_mostrados)) {
$nodos_mostrados[]=$anode->nid;
$changed = date('m/j', $anode->changed);
$items[] = l($anode->title, "node/". $anode->nid) . " ($changed)";
}
}
if(!$items) {
return;
} else {
return theme_item_list($items);
}
}
// vid = your vocabulary
function printRelatedVocabulary($vid, $limit=5) {
$nodos_mostrados=array();
$result = db_query("SELECT tid, name FROM {term_data} WHERE vid = %d", $vid);
while ($t = db_fetch_object($result)) {
$nodes = get_nodes($t->tid,$limit, $nodos_mostrados);
if ($nodes) {
print "<h3> $t->name </h3>";
print $nodes;
}
}
}
printRelatedVocabulary(2); // 2 = naissances
?>