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
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
Hey Andy :-)
I think you could do this, as you say, with a few lines of PHP code in your template, something like this:
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.
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.
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! :)
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
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
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
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.
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
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..
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..
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
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!
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,
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
Both your suggestions are still an excellent solution for blogging in Drupal 6.20.
my bit for this
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
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! :)