Adding next & previous links for node types within taxonomy terms (e.g. Image Galleries)

Last modified: June 23, 2007 - 20:19

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.

  1. In a text editor like notepad.exe or equivalent, create/edit a template.php file and paste the following snippet
  2. 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 .'&nbsp;&nbsp;'. $previous;}
      print
'&nbsp;&nbsp;['. $gallery .']&nbsp;&nbsp;';
      if (
$next){ print $next .'&nbsp;&nbsp;' .$last;}
      print
'</center></p>';
    }
?>

notes

  • once added to your template.php file, the next_prev function maybe called from any custom layout.tpl.php file.
  • Please add a comment/child page with examples of using the custom next_prev function in your layout.tpl.php files.

Small fix to step 1

bdimaggio - November 28, 2007 - 19:53

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

giuvax - October 8, 2008 - 15:47

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

giuvax - October 6, 2008 - 07:33

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...

camb416 - November 19, 2008 - 15:33

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?

clau_bolson - November 28, 2008 - 15:19

I am extremely interested in this! Image gallery without "next" and "previous" in each photo is extremely tiresome and will blow away any visitor.

 
 

Drupal is a registered trademark of Dries Buytaert.