4

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

1 Answer 1

3

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.

2
  • 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, 2010 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. Oct 10, 2010 at 15:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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