Adding next & previous links for node types within taxonomy terms (e.g. Image Galleries)
description
The following adds a custom next_prev function to your theme template.php file that allows you to insert NEXT | PREVIOUS type links in your layout.tpl.php files. Where layout might be node.tpl.php, node-image.tpl.php etc.
In the illustrative example snippet below, a simple NEXT | PREVIOUS link is inserted into a custom node-image.tpl.php file linking to the next and previous image within that gallery (taxonomy term).
step 1 of 2
Add the custom next_prev function to your template.php file.
- In a text editor like notepad.exe or equivalent, create/edit a template.php file and paste the following snippet
- Save your new/edited template.php file and upload it to your active theme folder
<?php
function next_prev($current_nid, $type, $button_type, $label, $class) {
$tid = db_result(db_query(db_rewrite_sql("SELECT tid FROM {term_node} WHERE nid = $current_nid;")));
if (empty($tid)){ //validate that the image 'does' have a tid
return '';
}
switch ($button_type) {
case 'next':
$sort= 'DESC';
$case = '< ';
break;
case 'prev':
$sort = 'ASC';
$case = '> ';
break;
case 'parent':
$name = db_result(db_query(db_rewrite_sql("SELECT name FROM {term_data} WHERE tid = $tid;")));
return l($label.$name, "$type/tid/$tid", array('title' => $name, 'class' => $class));
break;
case 'last':
$sql = "SELECT n.nid, n.title FROM node n INNER JOIN term_node t ON n.nid = t.nid";
$sql .= " INNER JOIN term_data r ON t.tid = r.tid WHERE n.type = '". $type ."'";
$sql .= " AND r.tid = $tid AND n.status = 1 ORDER BY nid ASC LIMIT 0 , 1";
$result = db_fetch_array(db_query(db_rewrite_sql($sql)));
return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
break;
case 'first':
$sql = "SELECT n.nid, n.title FROM node n INNER JOIN term_node t ON n.nid = t.nid";
$sql .= " INNER JOIN term_data r ON t.tid = r.tid WHERE n.type = '" .$type. "'";
$sql .= " AND r.tid = $tid AND n.status = 1 ORDER BY nid DESC LIMIT 0 , 1";
$result = db_fetch_array(db_query(db_rewrite_sql($sql)));
return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
break;
default:
return NULL;
break;
}
$sql = "SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid ";
$sql .= "INNER JOIN {term_data} r ON t.tid = r.tid WHERE n.type = '". $type ."' AND n.nid ". $case;
$sql .= $current_nid ." AND r.tid = ". $tid ." AND n.status = 1 ORDER BY nid ". $sort;
$result = db_fetch_array(db_query(db_rewrite_sql($sql)));
if (!$result) {
return NULL;
return l($label.$name, "$type/tid/$tid", array('title' => $name, 'class' => $class));
} else {
return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
}
}
?>step 2 of 2
Insert this snippet in your custom layout.tpl.php file and edit the $node->type to suit. This example snippet is intended for a custom node-image.tpl.php file. It inserts a link to the NEXT and PREVIOUS image within that image gallery (taxonomy term).
<?php
if ($terms && arg(0) == 'node' && is_null(arg(2))) {
$next = next_prev($node->nid, 'image', 'next', 'next>', 'link'); // replace 'test' with a valid class for the link
$previous = next_prev($node->nid, 'image', 'prev', '<previous', 'link');
$last = next_prev($node->nid, 'image', 'last', 'last>>', 'link');
$first = next_prev($node->nid, 'image', 'first', '<<first', 'link');
$gallery = next_prev($node->nid, 'image', 'parent', '', 'link');
print '<p><center>';
if ($previous){ print $first .' '. $previous;}
print ' ['. $gallery .'] ';
if ($next){ print $next .' ' .$last;}
print '</center></p>';
}
?>notes
- once added to your template.php file, the
next_prevfunction maybe called from any custom layout.tpl.php file. - Please add a comment/child page with examples of using the custom
next_prevfunction in your layout.tpl.php files.

Small fix to step 1
This is a super-useful piece of code and was working fine for me until I installed I18n, at which point I started getting a bunch of SQL errors like the following:
user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ';)' at line 1 query: SELECT tid FROM term_node LEFT JOIN i18n_node i18n ON n.nid = i18n.nid WHERE (i18n.language ='en' OR i18n.language ='' OR i18n.language IS NULL) AND ( nid = 125;) in /home/digitao0/public_html/ecologic/includes/database.mysql.inc on line 172.I fooled around with this a bit and discovered that some small changes to the SQL (adding brackets to all the tables that get referred to, removing the semicolon from the first SQL statement, adding a LEFT JOIN to bring the node table into that statement) fixed the problem. Here's what works for me:
<?php
function next_prev($current_nid, $type, $button_type, $label, $class) {
$tid = db_result(db_query(db_rewrite_sql("SELECT tn.tid FROM {term_node} tn LEFT JOIN {node} n ON tn.nid=n.nid WHERE tn.nid = $current_nid")));
if (empty($tid)){ //validate that the image 'does' have a tid
return '';
}
switch ($button_type) {
case 'next':
$sort= 'DESC';
$case = '< ';
break;
case 'prev':
$sort = 'ASC';
$case = '> ';
break;
case 'parent':
// $name = db_result(db_query(db_rewrite_sql("SELECT name FROM {term_data} WHERE tid = $tid;")));
return l($label, "$type/tid/$tid", array('title' => $label, 'class' => $class));
break;
case 'last':
$sql = "SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid";
$sql .= " INNER JOIN {term_data} r ON t.tid = r.tid WHERE n.type = '". $type ."'";
$sql .= " AND r.tid = $tid AND n.status = 1 ORDER BY nid ASC LIMIT 0 , 1";
$result = db_fetch_array(db_query(db_rewrite_sql($sql)));
return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
break;
case 'first':
$sql = "SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid";
$sql .= " INNER JOIN {term_data} r ON t.tid = r.tid WHERE n.type = '" .$type. "'";
$sql .= " AND r.tid = $tid AND n.status = 1 ORDER BY nid DESC LIMIT 0 , 1";
$result = db_fetch_array(db_query(db_rewrite_sql($sql)));
return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
break;
default:
return NULL;
break;
}
$sql = "SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid ";
$sql .= "INNER JOIN {term_data} r ON t.tid = r.tid WHERE n.type = '". $type ."' AND n.nid ". $case;
$sql .= $current_nid ." AND r.tid = ". $tid ." AND n.status = 1 ORDER BY nid ". $sort;
$result = db_fetch_array(db_query(db_rewrite_sql($sql)));
if (!$result) {
return NULL;
return l($label.$name, "$type/tid/$tid", array('title' => $name, 'class' => $class));
} else {
return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
}
}
?>
a little correction more
with this code:
case 'parent':// $name = db_result(db_query(db_rewrite_sql("SELECT name FROM {term_data} WHERE tid = $tid;")));
return l($label, "$type/tid/$tid", array('title' => $label, 'class' => $class));
break;
You lose the name of the parent gallery. The right code are the lines of the original version of the snippet. I solved it.
Bye! and thanks
A little correction
Hi,
I got an error on this snippet until I found the problem, with italian community help.
Drupal got an sql error because of the missing {} in the first two groups of sql queries.
You see, on the case 'default' the tables name are between {} and Drupal finds them.
My Drupal didn't find the tables in the case 'last' and 'first', I had to put the table names between {} and with this correction finally it's working.
Bye!
Sorting by Authored Date...
Thank you so much for these extremely helpful snippets!
I do have a question however... these snippets sort by node ID. I am entering a back catalog of content, so the IDs are out of order. Can someone assist me in changing the SQL lines so that the nodes returned are sorted by Authored Date?
Any help would be tremendously appreciated!
Shall this work on Drupal 6?
I am extremely interested in this! Image gallery without "next" and "previous" in each photo is extremely tiresome and will blow away any visitor.