Community Documentation

Adding next & previous links for same node type, translation-aware

Last updated August 23, 2009. Created by suit4 on February 8, 2007.
Edited by SLIU, Dublin Drupaller. Log in to edit this page.

description

This snippet adds a custom next_prev_same_type function to your theme template.php.
This allows you to insert Next and Previous links in your *.tpl.php file.

This function selects previous/next items depending on the time the node was created with a single query.
Only published nodes of the same node type like the current node are selected.

If the next/previous node id retrieved from the database is one of the current nodes' translations,
next_prev_same_type runs again to skip that node. In this case, there will be a new sql query.

Step 1 of 2

Insert this code into your template.php

<?php
function next_prev_same_type($nid=null, $path=null, $direction=null)
{
  if(
$nid){
   
// gather some node information
   
$node = node_load($nid);
   
$type = $node->type;
   
$created = $node->created;
   
   
// retrieve all node ids of this nodes' translations
   
$translation_ids = array();
    foreach(
$node->translation as $translation) {
      if(
$translation->status == 1){
       
$translation_ids[$key] = $translation->nid;
      }
    }
   
   
// switch some vars depending on direction
   
switch ($direction){
      case
'next':
       
$modifier = ">";
       
$order = "ASC";
       
$link_str = "Next project ›";
        break;
      case
'prev':
      default:
       
$modifier = "<";
       
$order = "DESC";
       
$link_str = "‹ Previous project";
    }
   
   
// get next / prev element from database
   
$query = db_query('select nid from {node} where type=\'%s\' AND status=1 AND nid!=%d AND created'.$modifier.'%d ORDER BY created %s, nid %s Limit 1',$type,$nid,$created,$order,$order);
    while (
$item = db_fetch_object($query)){
      if(
$item->nid!=$nid && !in_array($item->nid,$translation_ids)){
       
$nav_nid = $item->nid;
      }else{
       
// skip element, if it is a translation of the current node
       
return next_prev_same_type($item->nid,$path,$direction);
      }
    }
    if(
$nav_nid){
      return
l(t($link_str),$path."/".$nav_nid);;
    }
  }
}
?>

Step 2 of 2

Insert the code below somewhere in your *.tpl.php file (node.tpl.php, view_xyz.tpl.php, ...)

<?php
  $next
= next_prev_same_type($node->nid, "your/path/here", "next");
 
$prev = next_prev_same_type($node->nid, "yout/path/here", "prev");
  if(
$prev!= FALSE){
   
$links[] = $prev;
  }
  if(
$next!= FALSE){
   
$links[] = $next;
  }
  print
theme_links($links, $delimiter = ' ')
?>

OR

<?php
 
print next_prev_same_type($node->nid, "your/path/here", "next");
  print
next_prev_same_type($node->nid, "yout/path/here", "prev");
?>

Format as desired.

function variables

next_prev_same_type($nid=null, $path=null, $direction=null)
$nid is the current node
$path is the path to be used in the link
$direction is either 'next' or 'prev'

Notes

  • Once the function is placed in your template.php, it can be run on any page, template, block, ...
  • Add your comments below. Any ideas or modifications are welcome.

Comments

new version

I try to modify your code to adapt for Drupal 6.x, and new code can support multilanguage.

<?php
function next_prev_same_type($nid=null, $path=null, $direction=null)
{
  if(
$nid){
   
// gather some node information
   
$node = node_load($nid);
   
$type = $node->type;
   
$created = $node->created;

   
// switch some vars depending on direction
   
switch ($direction){
      case
'next':
       
$modifier = ">";
       
$order = "ASC";
       
$link_str = "Next:";
        break;
      case
'prev':
      default:
       
$modifier = "<";
       
$order = "DESC";
       
$link_str = "Previous:";
    }
  
   
// get next / prev element from database
   
$query = db_query('select nid, title from {node} where type=\'%s\' AND status=1 AND nid!=%d language=\'%s\' AND created'.$modifier.'%d ORDER BY created %s, nid %s Limit 1',$type,$nid,$node->language,$created,$order,$order);
    while (
$item = db_fetch_object($query)){
      if(
$item->nid!=$nid && !in_array($item->nid,$translation_ids)){
       
$nav_nid = $item->nid;
       
$nav_title = $item->title;
      }else{
       
// skip element, if it is a translation of the current node
       
return next_prev_same_type($item->nid,$path,$direction);
      }
    }
    if(
$nav_nid){
      return
t($link_str).l(t($link_str),$path."/".$nav_nid);;
    }
  }
}
?>

You can get more details and demo from http://www.easypays4u.com/?q=next-previous-link-in-node.

couldn't get it to work

Thanks for taking the time to adapt this, but my 6.17 installation keeps on insisint that there is an error in the SQL syntax. I failed to find any obvious errors in it, must be beyond my knowledge.

Domain Access

I'd just like to share my twist on this, I adjusted this originally because it was the best solution to having previous and next buttons for news articles across use of multiple domains (Domain Access).

The query itself wasn't written to well originally, I've only done a quick chop up of the original to get things working. Running Drupal 6.20. Just a note i attempted to mod the Prev/Next API Module to try and work over multiple domains but had no luck purely because i didn't want to hack the module directly itself.

Inside the node.tpl.php file:

<?php
  $next
= next_prev_same_type($node->nid, $node->type, $node->created, 'next');
 
$previous = next_prev_same_type($node->nid, $node->type, $node->created, 'previous');
?>

<?php
function next_prev_same_type($nid = NULL, $type = NULL, $created = NULL, $direction = NULL) {
  if(
$nid){
   
// switch some vars depending on direction
   
switch ($direction){
      case
'next':
       
$modifier = ">";
       
$order = "ASC";
       
$link_str = "Next:";
        break;
      case
'previous':
      default:
       
$modifier = "<";
       
$order = "DESC";
       
$link_str = "Previous:";
    }
 
   
//get the domain id's that can access this nid
   
$site_name = variable_get('site_name', 'Drupal');
   
$domain = db_fetch_object(db_query("SELECT domain_id from {domain} WHERE sitename = '%s'", $site_name));
   
   
//now get the previous/next node from the database
   
$query = db_query('SELECT n.nid, n.title FROM {node} n INNER JOIN {domain_access} d ON d.nid = n.nid WHERE d.gid = %s AND n.type=\'%s\' AND n.status=1 AND n.nid != %d AND n.created'
               
. $modifier . ' %d ORDER BY n.created %s, n.nid %s LIMIT 1',
               
$domain->domain_id, $type, $nid, $created, $order, $order
           
);
   
$item = db_fetch_object($query);
   
    if (!empty(
$item)) {
     
$nav_nid = $item->nid;
     
$nav_title = $item->title;
      return
l($nav_title, 'node/' . $nav_nid);
    }
   
    return
false;
  }
}
?>

About this page

Drupal version
Drupal 4.7.x

Theming Guide

Drupal’s online documentation is © 2000-2012 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License. Comments on documentation pages are used to improve content and then deleted.