creating a simple previous and next navigation for node pages

Events happening in the community are now at Drupal community events on www.drupal.org.
aprice42's picture

Hi all,

I am working on finally bringing my blog over from wordpress, and I am really struggling to find an elegant solution for adding a simple previous and next navigation to my posts. I am using a basic story content type for the posts, and using the date module to modify/enter the date of the post.

I have looked at the date browser view plugin, but it seems overly complicated and looks like it might be overkill for what I am trying to do...

I found this post: http://drupal.org/node/37767, but it looks like it is talking Drupal 5,
and this post: http://drupal.org/node/45050, but it adds taxonomy to the mix, which is more than I need here...

Seems like a need to create a function similar to the two examples I found above, that could be made available to my node-story.tpl.php file, but my PHP skills are lacking, so that seems a bit daunting...

Can anyone out there offer any suggestions/solutions to this seemingly basic need, there has to be an easy solution to this, right?

Thanks,
Andy

Comments

found custom pagers module

aprice42's picture

I found a module called custom pagers, that appears to do what I need... http://drupal.org/project/custom_pagers.

My only concern with it is trying to keep the number of contrib modules down so I can have an easy upgrade path to 7 when it is released.

So if anyone out there has any further suggestions, I would love to hear them...

Hey Andy :-) I think you

Justin Miller's picture

Hey Andy :-)

I think you could do this, as you say, with a few lines of PHP code in your template, something like this:

  1. Setup a SQL query to find the next node number up or down. For example, if we're on node 4 and it's a blog node and we want the previous blog node, do a query like "SELECT nid FROM {node} WHERE type = '%type' AND nid < %nid ORDER BY nid DESC LIMIT 1", inserting $node->type and $node->nid as the variables. That will look for nodes of the same type as the one we're on (blog) and the next lower node by node number. You'd do the same but with > for the next node up of the same type.

  2. Do a conditional to see if we got a result back (to account for times when you are at either end of your list of nodes) and if we have one, continue.

  3. Load the previous node as, say, $pnode, and create a link using l($pnode->title, 'node/' . $pnode->nid). That will link the node title to the path 'node/X'. Since you use the l() function, path aliases will get taken care of automatically by the theme rendering in the event that you don't use paths like 'node/X' by default (for example, 'yyyy/mm/dd/title', maybe).

Does that help?

Yes that does help - Thanks! :)

aprice42's picture

Thank you both for the input...

Justin, I used your suggestion in conjunction with the other info I found earlier...

The nodes are not all in order by nid (Because I imported a few hundred from a wordpress install), so, I based the nodes on the date field.

Here is what I came up with:

$query = db_rewrite_sql("SELECT nid FROM {content_type_story} WHERE field_date_value < '%s' ORDER BY field_date_value DESC LIMIT 1");
$result = db_query($query, $node->field_date[0]['value']);
$pnode = db_fetch_object($result);

$query = db_rewrite_sql("SELECT nid FROM {content_type_story} WHERE field_date_value > '%s' ORDER BY field_date_value ASC LIMIT 1");
$result = db_query($query, $node->field_date[0]['value']);
$nnode = db_fetch_object($result);

$prev_node = node_load($pnode->nid);
$next_node = node_load($nnode->nid);

This works perfectly!

One more question...
I have not worked with the database like this before, can anyone see any problems with the code that might create any security vulnerabilities? Do i need to close the database connection or anything like that?

You shouldn't have to close

Justin Miller's picture

You shouldn't have to close the DB, as this happens automatically on PHP script end (in this case, page render). You've used the right syntax for querying the DB, both in functions and properly escaping things. I think you're good :-)

I would highly recommend

duellj's picture

I would highly recommend taking drm's advice and using the views module to do the hard work for you rather than querying the database directly. Since you are querying against CCK tables, they can very easily change table names and field names (if you add that field to another node type, for example). Views will handle any CCK change automagically for you.

If you still want to query directly, you should use the CCK api get the correct table name:

<?php
$field
= content_fields('field_date_value');
$db_info = content_database_info($field);

$query = db_rewrite_sql("SELECT nid FROM {" . $db_info['table'] . "} WHERE field_date_value < '%s' ORDER BY field_date_value DESC LIMIT 1");
$result = db_query($query, $node->field_date[0]['value']);
$pnode = db_fetch_object($result);

$query = db_rewrite_sql("SELECT nid FROM {" . $db_info['table'] . "} WHERE field_date_value > '%s' ORDER BY field_date_value ASC LIMIT 1");
$result = db_query($query, $node->field_date[0]['value']);
$nnode = db_fetch_object($result);

$prev_node = node_load($pnode->nid);
$next_node = node_load($nnode->nid);
?>

See http://drupal.org/node/131452 for more info.

Views of one page at a time

drm's picture

Can't you just create a View that only display one node at a time, with a pager? If necessary you could use CCK to add an ordering field, if the date is not good for that. Then if you number them in fives or tens, you could easily insert new entries if need be.

I would second this approach.

datarazor's picture

I would second this approach. Use a view, and have it only display one node at a time, and have buttons for page next and back. Sort on whatever it is you want! You can then also have a side block for seeing recent posts, or by tag and/or by archive date just like in wordpress...

--
Fountain City Inc
Creative-Technical solutions
Beautiful websites built with Drupal
http://fountaincity.tech

Perhaps I'm missing something

jnicola's picture

Perhaps I'm missing something here, but how do you get the view to know where you currently are, and then only pull nodes moving forward from the current date?

I've got a few concepts, but since you two seem confident it's easy, I'd like to know what your recipe is!

Jesse Nicola -- Shredical six different ways to Sunday! -- My Portfolio

I agree but..

aprice42's picture

my goal is to get the previous and next navigation on the node page itself... I tried using views arguments to create a block view that would just produce a singular link to the next node / previous node in chronological order, but I wasn't getting anywhere with that...

thank you all for your input...

duellj, I will add that bit to my query, thanks...

asking for help..

straszko's picture

Hello Andy,
I think i have same problem as you had, but i can not resolve it (even with that hints you published in this thread...)

I found this article...
http://2bits.com/articles/simple-previous-next-navigation-node-title.html
It works fine but there is one problem - it sorts content by node-id (and i need it to sort by published-date)... I tried to modify this script but with no luck...

Could you please help me with that? I would appreciate your help...

Thank you..

here is what I used

aprice42's picture

Hi straszko,

Unfortunately, this is new territory for me, so I am not sure how helpful I can be with this... This is the code I ended up with thanks to the help above...

$query = db_rewrite_sql("SELECT nid FROM {content_type_story} WHERE field_date_value < '%s' ORDER BY field_date_value DESC LIMIT 1");
$result = db_query($query, $node->field_date[0]['value']);
$pnode = db_fetch_object($result);

$query = db_rewrite_sql("SELECT nid FROM {content_type_story} WHERE field_date_value > '%s' ORDER BY field_date_value ASC LIMIT 1");
$result = db_query($query, $node->field_date[0]['value']);
$nnode = db_fetch_object($result);

$prev_node = node_load($pnode->nid);
$next_node = node_load($nnode->nid);

Based on what you are saying I am guessing you have something like ORDER BY nid, in my case used ORDER BY field_date_value which is a field that stores the date I need to sort by, in your case it sounds like you want to use the node's created date - ORDER BY created, but I am not sure if that will work, maybe give that a try, and post what you find?

:) Andy

found it out! Thanks!

straszko's picture

Hi Andy,
Thanks for your reply.
Yes, you guessed right. I needed it to be order by 'created'. I've found the name of this variable inspecting my database ;) and after that i modified code from the website
http://2bits.com/articles/simple-previous-next-navigation-node-title.html
...and it seems to work!

That's 'my' piece of code:

function phptemplate_prev_next($current_node = NULL, $op = 'p') {
  // Node types to include in paging
  $node_types = array('my_blog');

  if ($op == 'p') {
    $sql_op = '<';
    $order = 'DESC';
  }
  elseif ($op == 'n') {
    $sql_op = '>';
    $order = 'ASC';
  }
  else {
    return NULL;
  }

  $output = NULL;
  foreach($node_types as $type) {
    $quoted_types[] = "'" . $type . "'";
  }
  $sql = "SELECT nid, title, created FROM {node} n
    WHERE created $sql_op %s
    AND type IN (" . implode(',', $quoted_types) . ")
    AND status = 1
    ORDER BY created $order
    LIMIT 1";
  $result = db_query($sql, $current_node->created, $type);
  $data = db_fetch_object($result);
  if (!isset($data->nid) || !$data->nid) {
    return NULL;
  }
  return l($data->title, "node/$data->nid", array('html' => TRUE));
}

...maybe someone will find it useful...

Thanks again for your reply!
Kind regards,
s.

Thanks for the code changes,

Lyndzay_M's picture

Thanks for the code changes, that was exactly what I needed for the blog I am working on.

I did have one problem when I put it in my template.php… I forgot to change $node_types = array('my_blog'); to $node_types = array('blog'); so when I first used it the only link that was appearing was a link to the current blog node. So if anyone is having that issue… that is the first place to look.

Hope my ignorance helps someone save a few minutes.

Thanks again
Lyndz

Confirmed

bitmaster's picture

Both your suggestions are still an excellent solution for blogging in Drupal 6.20.

my bit for this

aterchin's picture

this does both prev/next queries in the same function call and returns the info as an array. my preferred way to reuse code. parameters are more flexible also.

<?php
/**
* Previous / Next function for nodes, ordered by node creation date
*
* @param $current_node: node object or node id
* @param $node_types:  array of node types to query
*
* @return array
*/
function mymodule_prev_next_created($current_node = NULL, $node_types = array()) {
 
// make node object if only node id given
 
if (!is_object($current_node)) { $current_node = node_load($current_node->nid); }

 
// make an array if string value was given
 
if (!is_array($node_types)) { $node_types = array($node_types); }

 
// previous
 
$sql = "SELECT n.nid, n.title, n.created FROM {node} n
    WHERE n.created < %d AND n.type IN ('%s')
    AND n.status = 1 ORDER BY n.created DESC LIMIT 1"
;
 
$result = db_query($sql, $current_node->created, implode("','", $node_types));
 
$prev = db_fetch_object($result);

 
// next
 
$sql = "SELECT n.nid, n.title, n.created FROM {node} n
    WHERE n.created > %d AND n.type IN ('%s')
    AND n.status = 1 ORDER BY n.created ASC LIMIT 1"
;
 
$result = db_query($sql, $current_node->created, implode("','", $node_types));
 
$next = db_fetch_object($result);
 
  return array(
'prev' => $prev, 'next' => $next);
}
?>

Still Need Help

flavikun's picture

Does someone knows how to do the same(Previous and Next link on Nodes), but using a specific taxonomy vocabulary term(I have 2 vocabularies, one with the categories and another with tags) to limit the nodes. So the next and previous links are related only to the nodes within the same "category". This problem is driving me mad! I tried custom pagers but id did not work at all... Thanks! :)

Portland (Oregon)

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds:

Hot content this week