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

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

  $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

  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

loliearn’s picture

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.

ytsejam’s picture

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.

trothwell’s picture

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;
  }
}
?>