Displaying a previous – next post link in your Drupal theme

Drupal LogoIf you’re a convert to Drupal from a blogging platform like WordPress, you might miss the Previous/Next post links that allow visitors to read through the posts on your site in a chronological manner.

I’ve been searching for a solution to this for a while, but nothing I’ve found on Drupal.org has offered an acceptable solution for me. What I’m going to show you here is some code I’ve put together that retrieves the next and previous posts from the database and displays them for the user. If you are a Drupal guru and have suggestions for how to refine this, please share your knowledge in the comments.

Step 1: Mining The Database!

Before we get to the presentational aspects of the code, we need to find out what “nodes” come immediately before and after our post. Here’s the line of SQL code I’m using to extract the information:

SELECT nid, title FROM {node} WHERE nid < %d AND type = '%s' AND status = 1 ORDER BY nid DESC LIMIT 1

Explanation: This line retrieves the node before the current one. The “type = ‘%s'” allows this to only select from the same node type. This is useful if you have several different content types on your site, and you only want the script to select from the same type of content.

The “status” portion ensures only published nodes are shown, and the “limit” ensures that only one record is selected.

Step 2: Editing template.php

Jumping swiftly along, here’s the code I added to my template.php file.

function yourtheme_prevnext($nid,$ntype) {
//This selects the previous record and builds it into an HTML string using the Drupal "l" function to build the link
$result = db_query("SELECT nid, title FROM {node} WHERE nid < %d AND type = '%s' AND status = 1 ORDER BY nid DESC LIMIT 1",$nid,$ntype);
while ($row = db_fetch_array($result)) {
$outputstring .= "

“;
}
//This selects the next record and builds it into an HTML string as in the previous example
$result = db_query(“SELECT nid, title FROM {node} WHERE nid > %d AND type = ‘%s’ AND status = 1 ORDER BY nid ASC LIMIT 1″,$nid,$ntype);
while ($row = db_fetch_array($result)) {
//Finally, we wrap the output in a containing DIV element for themeing purposes
$outputstring .= ”

“;
}
$outputstring = ”

” . $outputstring . “

“;
print $outputstring;
}

This selects the previous and next records from the database and wraps them up in HTML. We use the Drupal l() function to create the links in the correct way.

Step 3: Call the function from node.tpl.php

OK, in order to get the HTML to display, you have to edit your node.tpl.php file. In the code snippet below, I’m going to call the code directly, but in reality, I only display this code when you’re looking at the full node, not the teaser view you might see in a category list.

nid,$node->type); ?>

The code to only display prevnext on full nodes is below

nid,$node->type);} ?>

Step 4: Add some styling to your CSS file

Now, in order to make it look good, add some code to your stylesheet. I’ll give you an example of what I used in my sandbox, but you may need to tweak it for your theme.

/* Post Navigation */
.post-navigation {font-size:12.5px;}
.prevpost {float:left;width:48%;text-align:left;}
.nextpost {float:right;width:48%; text-align:right;}

Your feedback

OK, I’ve shown you my code. I don’t know if anybody else has attempted this, but I’m happy to see other solutions or suggestions for how the code may be improved for this theme.

Please share!

7 comments

  1. Nice tip!thanx!!!i just addedfunction software_prevnext($nid,$ntype,$lang) {// the $lang variable because i’ve a multilanguage site $result = db_query(“SELECT nid, title FROM {node} WHERE nid < %d AND type = ‘%s’ AND language=’%s’    AND status = 1 ORDER BY nid DESC LIMIT 1”,$nid,$ntype,$lang);///

  2. stumbled upon your code while i was looking for something similar for drupal 7. if anyone needs it, here’s my code:<code> function themename_prevnext($nid, $ntype) { $prev = db_query(“SELECT nid, title FROM {node} WHERE nid < :nid AND type = :ntype AND status = 1 ORDER BY nid DESC LIMIT 1”, array(‘:nid’ => $nid, ‘:ntype’ => $ntype)); $next = db_query(“SELECT nid, title FROM {node} WHERE nid > :nid AND type = :ntype AND status = 1 ORDER BY nid DESC LIMIT 1″, array(‘:nid’ => $nid, ‘:ntype’ => $ntype));  foreach ($prev as $prev_node) { $prev_link = ‘<a href=”/’ . drupal_lookup_path(‘alias’, ‘node/’ . $prev_node->nid) . ‘” title=”previous”><span>’ .$prev_node->title. ‘</span></a>’; }  foreach ($next as $next_node) { $next_link = ‘<a href=”/’ . drupal_lookup_path(‘alias’, ‘node/’ . $next_node->nid) . ‘” title=”next”><span>’ .$next_node->title. ‘</span></a>’; }  $output = ‘ <ul id=”erf_pager”> <li>’. $prev_link .'</li> <li>’. $next_link .'</li> </ul> ‘;  return $output; }</code> 

    • This was exactly what I was looking for.One note though, the second query should be sorted ASC not DESC:$next = db_query(“SELECT nid, title FROM {node} WHERE nid > :nid AND type = :ntype AND status = 1 ORDER BY nid ASC LIMIT 1”, array(‘:nid’ => $nid, ‘:ntype’ => $ntype));

  3. You could also use if Previous/Next API if you don’t want to make your hands dirty with programming. This module provides next/previous blocks. You can see it in action on my Drupal blog.

    • That’s a gorgeous site, Davy – I love the design. And I actually came across your TOC post earlier today. I may have a use for that module in one of my own projects. Thanks for dropping by!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s