Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Let's assume that I have the following posts with the following titles:

  • PostA (is assigned to the 'category 1')
  • PostX (category 2)
  • PostB (category 1)
  • PostC (category 1)
  • PostD (category 1)
  • PostY (category 2)
  • PostE (category 1)
    ...

When a visitor will read the PostC, how can I display in the sidebar:


Previous Posts:
'PostA' (these are links here, of course)
'PostB'

Next Posts:
'PostD'
'PostE'


IOW the previous and the next 2 posts from the same category. (If a post has more categories we will choose the 1st one or the last one - it doesn't matter very much).

Also, if it is impossible to display the prev & next two posts it is acceptable also only one previous and next post. (I know that there are some WP functions for this but we prefer if it's possible two posts).

Also, of course, we want to display the first 'n' characters from the title (let's say 22). We don't want to display a static text like 'Next Post' or similar.

TIA

share|improve this question
add comment

1 Answer 1

up vote 3 down vote accepted

The existing WordPress functions are only for displaying one previous or next post. I quickly wrote functions to display any number of posts.

Paste the following in your theme functions.php file:

function custom_get_adjacent_posts( $in_same_cat = false, $previous = true, $limit = 2 ) {
    global $post, $wpdb;

    $op = $previous ? '<' : '>';

    if ( $in_same_cat ) {
        $cat_array = wp_get_object_terms($post->ID, 'category', array('fields' => 'ids'));

        $join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'category' AND tt.term_id IN (" . implode(',', $cat_array) . ")";
    }

    $posts = $wpdb->get_results( $wpdb->prepare( "SELECT p.* FROM wp_posts AS p $join WHERE p.post_date $op '%s' AND p.post_type = 'post' AND p.post_status = 'publish' ORDER BY p.post_date DESC LIMIT $limit", $post->post_date, $post->post_type ) );

    return $posts;
}

function custom_adjacent_posts_links( $in_same_cat = false, $previous = true, $limit = 2 ) {
    $prev_posts = custom_get_adjacent_posts( $in_same_cat, $previous, $limit );
    if( !empty($prev_posts) ) {
        echo ($previous) ? '<h3>Previous Posts:</h3>' : '<h3>Next Posts:</h3>';
        echo '<ul>';
        foreach( $prev_posts as $prev_post ) {
            $title = apply_filters('the_title', $prev_post->post_title, $prev_post->ID);
            echo '<li><a href="' . get_permalink( $prev_post ) . '">' .$title . '</a></li>';
        }
        echo '</ul>';
    }
}

In your sidebar file, where you want to display the posts, use custom_adjacent_posts_links( true ); to display the two previous posts in the same category and custom_adjacent_posts_links( true, false ); to display the next two posts in the same category.

share|improve this answer
    
Nice! I had an idea to filter query in get_adjacent_post() to increase number of posts returned, but it is hardcoded for get_row method and only returns one post, even if more results are returned from database. –  Rarst Oct 10 '10 at 14:54
    
Yep. Thanks a lot! Just a side note: Perhaps is better to use a PHP Code Widget to inject the calls in order to separate our custom code from the template's code. We use Executable PHP Code widget and it works great. Anyway an accepted answer. –  John Thomas Oct 10 '10 at 15:44
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.