Last updated March 27, 2008. Created by pwolanin on November 15, 2005.
Edited by add1sun, Heine, Amazon, sepeck. Log in to edit this page.
When viewing a node, I wanted the ability to page through to the next and previous article.
- Code is abstracted out into 2 different functions.
- You can specify the text to be used for the generated links.
- Uses l() instead of hardcoding directly generating the links using $nid. l() uses aliases if available and therefore generated links are consistent with the rest of the site.
- Uses a few class attributes to generated links so they can be styled.
These 2 functions (plus maybe a lot of other similar functions) can be abstracted out into a module.
- Create a file called template.php in your theme's folder if it does not already exist, assuming that theme is PHPTemplate-based.
- Copy the 2 functions
next_node()andprevious_node()into template.php. Copy the functions along with their complete definitions i.e. the whole body not only the function names. Make sure the functions are withing<?phpand?>tags. - Copy the code snippet to the place in node.tpl.php where you want the links to appear. These links should appear only when a node is view in its entirety so put them in a
if($page!=0).
For themes using other engines you will have to read the appropriate documentation to know where to put the code.
<?php
/**
* Enables theme developers to include a link to the node of the same type
* that comes immediately after the the node being currently viewed.
*
* A node has to be published and promoted to the front page to
* qualify as the 'next node'. Unpublished and nodes not promoted
* to front page are not considered. Access control is respected.
*
* Theme developers would normally use this in the template for a node.
*
* @param $node
* node whose next node is to be found.
* @param $next_node_text
* The text for the link that will be created. If no text is given
* then the title of the next node is used.
* @param $prepend_text
* Text to be prepended to the created link. It is not a part of the link.
* @param $append_text
* Text to be appended to the created link. It is not a part of the link.
*
*/
function next_node($node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL)
{
$query = db_rewrite_sql("SELECT nid, title FROM {node} WHERE created > '%s' AND status=1 and promote=1 AND type='%s' ORDER BY created ASC LIMIT 1", "node", "nid");
$result = db_query($query, $node->created, $node->type);
$next_node = db_fetch_object($result);
if(!$next_node_text) // If next_node_text is not specified then use the next node's title as the text for the link.
{
$next_node_text = $next_node->title;
}
if($next_node->nid!=NULL)
{
return $prepend_text.l($next_node_text, 'node/'.$next_node->nid, array('title'=>'Go to the next post "'.$next_node_text.'"', 'class'=>'goto-previous-node')).$append_text;
}
else // There is no next node for this node...
{
return NULL;
}
}
/**
* Enables theme developers to include a link to the node of same type
* that comes immediately before the the node being currently viewed.
*
* A node has to be published and promoted to the front page to
* qualify as the 'previous node'. Unpublished and nodes not promoted
* to front page are not considered. Access control is respected.
*
* Theme developers would normally use this in the template for a node.
*
* @param $node
* node whose next node is to be found.
* @param $previous_node_text
* The text for the link that will be created. If no text is given
* then the title of the previous node is used.
* @param $prepend_text
* Text to be prepended to the created link. It is not a part of the link.
* @param $append_text
* Text to be appended to the created link. It is not a part of the link.
*
*/
function previous_node($node, $previous_node_text=NULL, $prepend_text=NULL, $append_text=NULL)
{
$query = db_rewrite_sql("SELECT nid, title FROM {node} WHERE created < '%s' AND status=1 and promote=1 AND type='%s' ORDER BY created DESC LIMIT 1", "node", "nid");
$result = db_query($query, $node->created, $node->type);
$previous_node = db_fetch_object($result);
if(!$previous_node_text) // If previous_node_text is not specified then use the previous node's title as the text for the link.
{
$previous_node_text = $previous_node->title;
}
if($previous_node->nid!=NULL)
{
return $prepend_text.l($previous_node_text, 'node/'.$previous_node->nid, array('title'=>'Go to the previous post "'.$previous_node_text.'"', 'class'=>'goto-previous-node')).$append_text;
}
else // This node does not have a previous node...
{
return NULL;
}
}
?>Alternately you use this return statement: return $prepend_text.l($next_node_text, 'node/'.$next_node_nid, array('title'=>'Go to the next post "'.$next_node_text.'"', 'class'=>'goto-next-node')).$append_text;
I used the above code in my node.tpl.php just below the node body like this:
<?php
if($page!=0)
{
$previous_node_link = previous_node($node, NULL, '<< ', NULL);
$next_node_link = next_node($node, NULL, NULL, ' >>');
print '<div class="previous-next-links">';
if($previous_node_link && $next_node_link)
{
print $previous_node_link.' | '.$next_node_link;
}
else if($previous_node_link)
{
print $previous_node_link;
}
else if($next_node_link)
{
print $next_node_link;
}
print '</div>';
}
?> update:
The above functions, though functional are huge resource hogs. Doing a node_load on every node until you find the correct taxonomy term has a huge performace impact. This can be overcome by with some simple sql joins. Here is an updated function. I've also combined the 2 functions into one.
<?php
function node_sibling($dir = 'next', $node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL, $tid = FALSE){
if($tid){
$query = 'SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid=tn.nid WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' %d AND n.type = "%s" AND n.status=1 '
. 'AND tn.tid = %d ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$result = db_query($query, $node->nid, $node->type, $tid);
}else{
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' %d AND n.type = "%s" AND n.status=1 '
. 'ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$result = db_query($query, $node->nid, $node->type);
}
if($row = db_fetch_object($result)){
$text = $next_node_text ? $next_node_text : $row->title;
return $prepend_text . l($text, 'node/'.$row->nid, array('rel' => $dir)) . $append_text;
}else{
return NULL;
}
}
?>An alternate solution can be found here: Adding next & previous links for node types within taxonomy terms (e.g. Image Galleries)
For Drupal 5.x, The Custom Pagers module might help by giving this a user interface: http://drupal.org/project/custom_pagers
Comments
Limit nodes to the current language only with i18n
To limit returned nodes in the current language only with i18n I modified the above code by adding db_rewrite_sql.
<?phpfunction node_sibling($dir = 'next', $node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL, $tid = FALSE){
if($tid){
$query = 'SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid=tn.nid WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' %d AND n.type = "%s" AND n.status=1 '
. 'AND tn.tid = %d ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$result = db_query(db_rewrite_sql($query), $node->nid, $node->type, $tid);
}else{
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' %d AND n.type = "%s" AND n.status=1 '
. 'ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$result = db_query(db_rewrite_sql($query), $node->nid, $node->type);
}
if($row = db_fetch_object($result)){
$text = $next_node_text ? $next_node_text : $row->title;
return $prepend_text . l($text, 'node/'.$row->nid, array('rel' => $dir)) . $append_text;
}else{
return NULL;
}
}
?>
---
Drupal community solutions { Web 2.0 solutions for drupal }
--
Drupal community solutions { Web 2.0 solutions for drupal }
This code for drupal 6.8?
i try to use this code with drupal 6.8 and the garland theme, but if i follow the instructions the main css file doesn't load in full-story-view and i get an unformattet view where only the text is displayed without any css styling.
Are there Changes in the code need to get this code running with drupal 6.8?
I am not a programmer thats why my question.
best wishes from germany, Holger
IT-News und IT-Jobs auf w3Projekt.com
best wishes from germany, Holger
IT-News und IT-Jobs auf w3Projekt.com
For D7
for D7 this works:
<?php
function node_sibling($dir = 'next', $node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL, $tid = FALSE){
if($tid){
$query = 'SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid=tn.nid WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' :nid AND n.type = :type AND n.status=1 '
. 'AND tn.tid = :tid ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
//use fetchObject to fetch a single row
$row = db_query($query, array(':nid' => $node->nid, ':type' => $node->type, ':tid' => $tid))->fetchObject();
}else{
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' :nid AND n.type = :type AND n.status=1 '
. 'ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
//use fetchObject to fetch a single row
$row = db_query($query, array(':nid' => $node->nid, ':type' => $node->type))->fetchObject();
}
if($row) {
$text = $next_node_text ? $next_node_text : $row->title;
return $prepend_text . l($text, 'node/'.$row->nid, array('rel' => $dir)) . $append_text;
return $row->nid;
} else {
return FALSE;
}
}
?>
Could you be more specific? I
Could you be more specific?
I changed function mythemename_node_sibling
and copied your code to template.php, but previous, next don't show. Do i need to add code to node.tpl.php?
Thank you for your help.
Same problem here
Same problem here
Your imagination is your limitation
the output contains 2
the output contains 2 returns,
the correct code would be for D7:
in template.php:
<?php
function node_sibling($dir = 'next', $node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL, $tid = FALSE){
if($tid){
$query = 'SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid=tn.nid WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' :nid AND n.type = :type AND n.status=1 '
. 'AND tn.tid = :tid ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
//use fetchObject to fetch a single row
$row = db_query($query, array(':nid' => $node->nid, ':type' => $node->type, ':tid' => $tid))->fetchObject();
}else{
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' :nid AND n.type = :type AND n.status=1 '
. 'ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
//use fetchObject to fetch a single row
$row = db_query($query, array(':nid' => $node->nid, ':type' => $node->type))->fetchObject();
}
if($row) {
$text = $next_node_text ? $next_node_text : $row->title;
return $prepend_text . l($text, 'node/'.$row->nid, array('rel' => $dir)) . $append_text;
} else {
return FALSE;
}
}
?>
in your node.tpl.php:
<?php
$next = node_sibling('next',$node,NULL,NULL,NULL,FALSE);
$previous = node_sibling('previous',$node,NULL,NULL,NULL,FALSE);
print $previous.'||'.$next;
?>
Content field instead of TID?
How do I replace $tid to CCK Field value?
I uses cck field named
"field_type" (select list)as taxonomy replacement outputted as<?php$content['field_type']['#items']['0']['value']
?>
Great Code Quick Question
Hey I implemented the code and the functionality is exactly what I need. However I would like the buttons to be more generic and have the labels say next and previous instead of the title of the next node. Any ideas on how to modify this to accomplish that?
prev / next text
@dax444:
If you look at the code, the text to display is the third parameter of the function call:
$next = node_sibling('next',$node,'Your text to be displayed goes here',NULL,NULL,FALSE);If there is a value in that position it is used instead of the node title.
Great code, thanks to all.
Thanks for the code.
thanks for the code it really works. But i have little problem with it.
1. It show next and previous links in the teasser and on the Content Type pages as well. how to show the next-previous option only in content type Article.
2. the next-previous links appears below the tag: and category. I want to show it right after the article.
I am using analytic theme for my site.
Thanks in advance for ur help..
www.daenotes.com
Scroll by term
Hello,
the code works perfectly for all nodes of the site (Drupal 7). Thank you.
How to change this function to scroll through the nodes of a specific term?
For example if we have in taxonomy:
Vocabulary: Vehicles, terms: cars, trucks, planes
Is it possible to scroll only the nodes of a term (planes for example)?
Thank you for your reply
By Term
The last parameter of the function is for a $tid. Try substituting your term id where it says FALSE.
<?php$previous = node_sibling('previous',$node,'Previous Poster',NULL,NULL,FALSE);
?>
Error table term_node doesn't exist
When I replace "False" with another data, I get an error :
Base table or view not found: 1146 Table 'sitename.term_node' doesn't exist.
Table term_node exists on drupal drupal 6 but not 7.
Table term_node doesn't exist
In D7 term_node table was replaced by taxonomy_index.
Code listed below works for me (excluding error notice about "undefined $terms variable"). Not sure if it's a good code example though.
<?php
function taxonomy_node_get_terms($node, $key = 'tid') {
if (!isset($terms[$node->vid][$key])) {
$query = db_select('taxonomy_index', 'r');
$t_alias = $query->join('taxonomy_term_data', 't', 'r.tid = t.tid');
$v_alias = $query->join('taxonomy_vocabulary', 'v', 't.vid = v.vid');
$query->fields( $t_alias );
$query->condition("r.nid", $node->nid);
$result = $query->execute();
$terms[$node->vid][$key] = array();
foreach ($result as $term) {
$terms[$node->vid][$key][$term->$key] = $term;
}
}
return $terms[$node->vid][$key];
}
function node_sibling($dir = 'next', $node, $next_node_text=NULL){
$query = 'SELECT n.nid, n.title FROM {node} n INNER JOIN {taxonomy_index} ti ON n.nid = ti.nid WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' :nid AND n.type = :type AND n.status=1 '
. 'AND ti.tid = :tid ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$terms = taxonomy_node_get_terms($node);
foreach ($terms as $term) {
$row = db_query($query, array(':nid' => $node->nid, ':type' => $node->type, ':tid' => $term->tid))->fetchObject();
}
if($row) {
$text = $next_node_text ? $next_node_text : $row->title;
return l('<div id="'.$dir.'" class="boxes"></div>', 'node/'.$row->nid, array('rel' => $dir,'html' => true));
} else {
return FALSE;
}
}
?>
Code in node.tpl
what is the code to insert into node.tpl?
This does not work:
<?php
$next = node_sibling('next',$node,NULL,NULL,NULL,FALSE);
$previous = node_sibling('previous',$node,NULL,NULL,NULL,FALSE);
print $previous.'||'.$next;
?>
Thanks.
It's ok !
I have not set my div previous and next.
I see now on my page previous and next links.
Thank you again.
Function taxonomy_node_get_terms / version d6
Hello,
your code works perfectly for Drupal 7.
But I must use this function on a website created in drupal 6.
Have you a version for Drupal 6 ?
Thanks.
For Drupal 6
In template.php :
function node_sibling($dir = 'next', $node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL, $tid = FALSE){if($tid){
$query = 'SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid=tn.nid WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' %d AND n.type = "%s" AND n.status=1 '
. 'AND tn.tid = %d ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$result = db_query($query, $node->nid, $node->type, $tid);
}else{
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' %d AND n.type = "%s" AND n.status=1 '
. 'ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$result = db_query($query, $node->nid, $node->type);
}
if($row = db_fetch_object($result)){
$text = $next_node_text ? $next_node_text : $row->title;
return l('<div class="pager-'.$dir.'"></div>', 'node/'.$row->nid, array('rel' => $dir,'html' => true));
}else{
return NULL;
}
}
In node.tpl.php :
<?php$terms = taxonomy_node_get_terms($node);
$last_tid = end($terms)->tid;
$previous = node_sibling('previous',$node,NULL,NULL,NULL,$last_tid);
$next = node_sibling('next',$node,NULL,NULL,NULL,$last_tid);
print $previous.''.$next;
?>
How would one display the
How would one display the previous / next buttons on every node? Currently the first and last nodes are missing one button or the other.
multilanguage?
Hi.
I put this code and it works fine. But i run a multilanguage site and when i use the previous/next-links, they show all nodes, independent from the language.
Is there a possibility to fix this?
Is it possible to use this code in a view?
Thanks!
got it fixed... <?phpfunction
got it fixed...
<?php
function node_sibling($dir = 'next', $node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL, $tid = FALSE){
global $language;
if($tid){
$query = 'SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid=tn.nid WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' :nid AND n.type = :type AND n.status=1 AND '
. 'AND tn.tid = :tid AND n.language = :language ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
//use fetchObject to fetch a single row
$row = db_query($query, array(':nid' => $node->nid, ':type' => $node->type, ':tid' => $tid, ':language' => $language->language))->fetchObject();
}else{
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.nid ' . ($dir == 'previous' ? '<' : '>') . ' :nid AND n.type = :type AND n.status=1 AND n.language = :language '
. 'ORDER BY n.nid ' . ($dir == 'previous' ? 'DESC' : 'ASC');
//use fetchObject to fetch a single row
$row = db_query($query, array(':nid' => $node->nid, ':type' => $node->type, ':language' => $language->language))->fetchObject();
}
if($row) {
$text = $next_node_text ? $next_node_text : $row->title;
return $prepend_text . l($text, 'node/'.$row->nid, array('rel' => $dir)) . $append_text;
} else {
return FALSE;
}
}
?>
link attributes fix
The link structure for adding attributes such as class or rel is incorrect. It should be:
<?phpreturn $prepend_text . l($text, 'node/'.$row->nid, array('attributes' => array('rel' => $dir))) . $append_text;
?>
Sort by created column rather than by nid column
This code orders by nid, so the "next" nid and title returned from the db_query call are next as determined by the node id.
This works great if you are entering nodes without modifying their creation date, but if you are, for example, entering back issues of content and modifying the node's creation date to be before a previously-entered node's creation date, this function will still return the more-recently-entered node as the "next" node for the less-recently-entered node.
But if the more-recently-entered node with node id 2 is dated earlier than the less-recently-entered node with node id 1, then you might want nid 1 to be the "next" value of nid 2 rather than the other way around.
I have modified this query to order the selected rows not by node id but rather by created date. Now if you change the created date for a given node so that the order of nodes as determined by created date is changed, the previous and next nodes will be updated accordingly. I wrote this for Drupal 6 but the only interesting part is the query and that will be identical across D6/D7/D8.
Also note: it is my understanding that queries enclosed in single quotes are not portable to PostgreSQL, though of course they are fully compatible with MySQL. In addition, Drupal SQL coding conventions specify that the %s db_query placeholder be enclosed in single quotes, so I have replaced the double quotes used previously with escaped single quotes.
Here's the revised function to find previous and next nodes by term as ordered by creation date rather than node id:
<?phpfunction node_sibling($dir = 'next', $node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL, $tid = FALSE) {
if ($tid) {
$query = 'SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid=tn.nid WHERE '
. 'n.created ' . ($dir == 'previous' ? '<' : '>') . ' %d AND n.type = \'%s\' AND n.status=1 '
. 'AND tn.tid = %d ORDER BY n.created ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$result = db_query($query, $node->created, $node->type, $tid);
} else {
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.created ' . ($dir == 'previous' ? '<' : '>') . ' %d AND n.type = \'%s\' AND n.status=1 '
. 'ORDER BY n.created ' . ($dir == 'previous' ? 'DESC' : 'ASC');
$result = db_query($query, $node->created, $node->type);
}
if ($row = db_fetch_object($result)) {
$text = $next_node_text ? $next_node_text : $row->title;
return $prepend_text . l($text, 'node/'.$row->nid, array('attributes' => array('rel' => $dir))) . $append_text;
} else {
return NULL;
}
}
?>
Let me know if you spot any issues with it.
Alphabool
Thanks
!
This returns an error for
This returns an error for me:
Sorry, I'm not good enough with PHP to troubleshoot myself...
Edit: Oh, right, that's for Drupal 6. I missed that part!
Got some help. For Drupal 7, without the taxonomy part:
<?php
function node_sibling($dir = 'next', $node, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL){
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.created ' . ($dir == 'previous' ? '<' : '>') . ' :created AND n.type = :type AND n.status=1 '
. 'ORDER BY n.created ' . ($dir == 'previous' ? 'DESC' : 'ASC');
//use fetchObject to fetch a single row
$row = db_query($query, array(':created' => $node->created, ':type' => $node->type))->fetchObject();
if($row) {
$text = $next_node_text ? $next_node_text : $row->title;
return $prepend_text . l($text, 'node/'.$row->nid, array('rel' => $dir)) . $append_text;
} else {
return FALSE;
}
}
?>
Megan McDermott
The Webmaster Forums | Drupal theming services
Improved Drupal 7 version without taxonomy
I've improved the Drupal 7 version (without taxonomy):
<?php
/**
* Gets previous and next node.
*/
function node_sibling($node, $dir = 'next', $prepend_text = '', $append_text = '', $next_node_text = NULL) {
$query = 'SELECT n.nid, n.title FROM {node} n WHERE '
. 'n.created ' . ($dir == 'prev' ? '<' : '>') . ' :created AND n.type = :type AND n.status = 1 '
. "AND language IN (:lang, 'und') "
. 'ORDER BY n.created ' . ($dir == 'prev' ? 'DESC' : 'ASC') . ' LIMIT 1';
//use fetchObject to fetch a single row
$row = db_query($query, array(':created' => $node->created, ':type' => $node->type, ':lang' => $node->language))->fetchObject();
if ($row) {
drupal_add_html_head_link(array(
'rel' => $dir,
'type' => 'text/html',
'title' => $row->title,
// Force the URL to be absolute, for consistency with other <link> tags
// output by Drupal.
'href' => url('node/' . $row->nid, array('absolute' => TRUE)),
));
$text = $next_node_text ? t($next_node_text) : $row->title;
return t($prepend_text) . l($text, 'node/' . $row->nid, array('attributes' => array('rel' => array($dir)))) . t($append_text);
} else {
return FALSE;
}
}
?>
Calling that D7 version, and some CSS
I'm using the above version - thanks scito & everyone else who's contributed to this thread.
It took me a while to work out how to call it, so thought I would share that here:
<div class="older_and_newer"><?php $older = node_sibling($node,'prev','Older: ',NULL,NULL);
$newer = node_sibling($node,'next','Newer: ',NULL,NULL);
print '<div class="older_post">'.$older.'</div>';
print '<div class="newer_post">'.$newer.'</div>'; ?>
</div><!-- end of older_and_newer -->
(obviously the "Older:" and "Newer:" labels are optional)
I'm then using those divs with CSS to send the two links left and right as follows:
.older_post
{
float:left;
}
.newer_post
{
text-align:right;
}
(though depending on where you're putting the links, that may or may not be appropriate.)
h.t.h.
Improved D7 call
Improvements:
a) safe (as far as I can tell) to put into page.tpl.php without throwing errors, as discussed further down-thread.
b) makes neater HTML, due to additional tabs (\t) and newlines (\n).
c) adds condition for what kind of pages to put it on (in my case, "Article" pages).
<?php /* next & prev links, for Articles only */
if ( isset($node) )
{
if ($node->type == 'article')
{
$older = node_sibling($node,'prev','Older: ',NULL,NULL);
$newer = node_sibling($node,'next','Newer: ',NULL,NULL);
print "<div class='older_and_newer'>\n";
print "\t<div class='older_post'>".$older."</div>\n";
print "\t<div class='newer_post'>".$newer."</div>\n";
print "</div> <!-- end of older_and_newer -->\n";
}
}
?>
Two errors "Undefined variable" and Trying to get property of.."
Hello there I hope you can help me out with my D7 project. I want to use this code in my page.tlp.php but I get two errors.
One time I get :"Undefined variable: node in include()" in line
"$next = node_sibling('next',$node,NULL,NULL,NULL,FALSE);"And 5 times I get: "Trying to get property of non-object in node_sibling()" in line
$row = db_query($query, array(':created' => $node->created, ':type' => $node->type))->fetchObject();I do get the menulinks in the page that allow me to go to the next and previous page by clicking on the name of the link. However I don't see the "next" and "previous" links.
I think it has to do with me putting it in my page.tlp.php, what do I need to change for it to work here?
First, you say I think it has
First, you say
I think it has to do with me putting it in my page.tlp.php, what do I need to change for it to work here?
The function definition
function node_sibling() {...}needs to go in your template.php file or in a custom module. Then you can call it within page.tpl.php and assign the return to a variable, like $next.As to your error, the second error follows directly from the first. What appears to be happening is that $node is undefined, so once passed it is not an object and so getting a property, like $node->created, will fail. I do not know why it is identified as not an object. In my implementation I actually pass the nid, so I define
node_siblingasfunction blog_sibling($dir = 'next', $nid, $next_node_text=NULL, $prepend_text=NULL, $append_text=NULL) {...}</code, call <code>$next = blog_sibling('next', $node->nid)and then do$node = node_load($nid)to get $node withinnode_sibling. Don't know why your approach isn't working though, and let me know if I'm unclear....Alphabool
Calling from page.tpl.php and getting intermittent errors
Thanks grimmweb & alphabool.
Yes alphabool that does make sense. I've got the function in template.php and the call for it in page.tpl.php.
It worked OK when I had the call in node.tpl.php, but that's not actually where I want the links to appear. When I moved it to page.tpl.php, I started getting the same kind of errors as grimmweb reports above. At first glance, I agree it looks like page.tpl.php somehow not knowing what the node is.
What's really weird though is that (a) the links still appear fine every time (so it evidently does know where the node is really), and (b) the error message comes and goes to no pattern I can predict!
Let's say I call the same page again and again (using a sidebar block which offers a link to that page).
Second to last page in sequence. Errors appear: no, no, no, yes, no, no, yes, no, yes, no, no, no, yes, no, yes, no, yes, no, no, yes, no, yes, no, yes, no, yes, no, yes, no, no, yes, no, no, no, yes
End page in sequence (most recent date). Errors appear: no, yes, yes, yes, yes, yes, yes, all yes for 10 or 20 more
Back to second to last page in sequence. Errors appear: yes, yes, yes, no, no, no, no, no, no, no, no, no, no, no, no, yes, no, no, no, yes, no, yes, no, yes, yes
First page in sequence (oldest date). Errors appear: no, no, no, no, no, yes, no, no, no, no, yes, no, no, no, no, no, no, yes, no
I'm not saying there's no pattern there at all: the end of sequence page seems to be behaving differently from the others. (Though maybe if I'd carried on long enough that too would've spontaneously lost the error message. Not taking for granted that it wouldn't.)
But it doesn't make sense to me. Making the same call more than once, usually I'd expect it either to behave the same, or to behave differently depending on what had happened just before. I mean e.g. if the error seemed to start by calling the end of sequence page, then persisted to the next 1 call to a mid-sequence page, then disappeared... well, that would suggest some kind of a theory (e.g. that it was getting confused on the end of sequence page by lack of a "next" node). This, I don't know what could be changing from call to call.
Any clues?
(Edited to add: This is D7.7)
Got it working OK
Here's what I found out:
http://drupal.org/node/303492 says that error messages of this nature come direct from PHP, and if you want, you can switch PHP to a less verbose level of logging.
Basically, it's PHP telling you that your code is a bit dodgy. Which, if you put it into page.tpl.php, it is in principle, because some pages don't have a node (e.g. if the page is created by Views and the View is empty). In actual fact my pages did all have nodes, but technically it's unsafe to assume that. So I think that's probably why PHP throws the error.
Personally I would rather write safe code than switch off error messages :-) so have rewritten using an "isset"- see further up thread.
(I still don't know why it only reports the error on some reloads of the page and not others.)
Had to make a node.tpl.php
I eventually had to make a node.tpl.php and got a working right there. However when I put the same code in my page.tpl.php (I still want to solve this) the function fails, I tried the things you suggested but no luck. Perhaps other things are at play here.
Alphabool, thank you for your reply. I suspect you are right. However I will no longer pursue to get it working in the page.tpl.php.
Thanks.
Thanks.
Drupal网站建设