WordPress 2.8 Single Post Navigation Widget

Since WordPress 2.8, there is a new Widget API. In our post Build A WordPress 2.8 Widget With The New Widget API, I have used a simple example to describe how to build a Widget. This time Heiko and I’ve created something more complex.

It is a Post Navigation Widget, which lists in the single post view (single.php) a specific number of posts which were published before this post and a certain number of posts which were published after this post. I think this is a nice way to show older posts in the sidebar. Here’s a screenshot, left of the backend, right of the sidebar:

WordPress Single Post Navigation Widget

I created a query to check if the class WP_Widget even exists, so the user won’t get any error messages in WordPress versions prior to 2.8.

 'wpe_widget_post_navi', 'description' => __( "Some posts before and after the current post") );
            $this->WP_Widget('wpe-post-navi', __('WPE Single Post Navigation'), $widget_ops);

        function widget($args, $instance) {
            if(is_single()) {
                global $post, $wpdb;

                if ( !$number = (int) $instance['number'] )
                    $number = 5;
                elseif( $number < 1 )
                    $number = 1;
                elseif( $number > 10 )
                    $number = 10;

                $title_before 		= apply_filters('widget_title', empty($instance['title_before']) ? 'Posts before' : $instance['title_before']);
                $title_after	 	= apply_filters('widget_title', empty($instance['title_after']) ? 'Posts after' : $instance['title_after']);
                $before_widget_2	= preg_replace("/(wpe\-post\-navi-\d+)/", "$1-1", $before_widget);

                $querystr = "
                    SELECT *
                    FROM $wpdb->posts wposts
                    WHERE wposts.ID != $post->ID
                    AND wposts.post_type = 'post'
                    AND wposts.post_status = 'publish'
                    AND wposts.post_date %s '$post->post_date'
                    ORDER BY wposts.post_date %s
                    LIMIT $number

                $leading_posts = $wpdb->get_results(sprintf($querystr, '<', 'DESC'), OBJECT);
                $trailing_posts = $wpdb->get_results(sprintf($querystr, '>', 'ASC'), OBJECT);

                if ($trailing_posts && count($trailing_posts)) {
                    echo $before_widget_2 . $before_title . $title_before . $after_title . "
    "; $trailing_posts = array_reverse($trailing_posts); foreach ($trailing_posts as $post) { setup_postdata($post); ?>
  • " . $after_widget; } if ($leading_posts && count($leading_posts)) { echo $before_widget . $before_title . $title_after . $after_title . "
      "; foreach ($leading_posts as $post) { setup_postdata($post); ?>
    • " . $after_widget; } wp_reset_query(); } } function update( $new_instance, $old_instance ) { $instance = $old_instance; $instance['title_before'] = strip_tags($new_instance['title_before']); $instance['number'] = (int) $new_instance['number']; $instance['title_after'] = strip_tags($new_instance['title_after']); return $instance; } function form( $instance ) { $title_before = ($instance['title_before'] == '') ? 'Posts before' : esc_attr($instance['title_before']); $title_after = ($instance['title_after'] == '') ? 'Posts after' : esc_attr($instance['title_after']); if ( !$number = (int) $instance['number'] ) $number = 5; elseif ( $number < 1 ) $number = 1; elseif ( $number > 10 ) $number = 10; ?>

      (at most 10)

Most of this should be self-explanatory. Now to the function widget () , which does the actual work. Here we had to do a little trick, because the widget actually creates 2 widgets, and they would get the same ID. That wouldn’t be valid, so the code adds a -1 to one of the widget elements:

$before_widget_2 = preg_replace("/(wpe\-post\-navi-\d+)/", "$1-1", $before_widget);

2 queries are getting executed. One for the posts before this post and one for the posts after this post. if posts are available they will show up on the sidebar.

Download Widget.
Then unpack and copy the code into functions.php. Please note, the widget is for WordPress 2.8.





9 responses to “WordPress 2.8 Single Post Navigation Widget”

  1. Wallace Avatar

    Great plugin!
    By the way, can we control how many words in excerpts?

  2. Home Trends Avatar

    This is nice tweak…. and add some Widget feature make this code very useful for created extra ordinary wordpress

  3. luis Avatar


    this page uses some widget to show the previous post name and the next post name, how do you do it? using this widget?


  4. luis Avatar

    hi, I found that it was simpler than that and there is a function (the regular function) for these links in wordpress, so I forgot to look closely at the functions that were already there.


  5. zauberer & hütchenspieler Avatar

    Hi, thanks for this nice widget, i use it and hope lot of users will like it. One question, how can i give the headlines befor & after an h2 for the layout?

  6. Michael Avatar

    @zauberer: In your functions.php you have a function

            'name' => 'Sidebar',
            'before_widget' => '
  7. ', 'after_widget' => '
  8. ', 'before_title' => '

    ', 'after_title' => '

    ' ));

    You can change the values to your need.

  9. Dan Avatar

    How would one include this in a plugin as oppose to functions.php?

  10. redlex Avatar

    After following this tutorial, I couldn’t get a couple of things to work. The permalinks will not work with the register_post_type() and arrays outlined in a function; I simply removed this and permalinks worked fine