Get Previous & Next posts by Post ID

How can I go about getting the previous and next posts from outside the loop? Everything I try to do aside from the custom SELECT query (using get_posts or WP_Query) breaks stuff further down the page.

I currently have a recursive function which will hopefully find the first “previous” post which satisfies a certain condition. I grab the first value to test from get_previous_post() but don’t know how to get the previous_previous_post().

add_action( 'wp_ajax_nopriv_myajax-submit', 'ajax_project_load' );
add_action( 'wp_ajax_myajax-submit', 'ajax_project_load' );

function ajax_project_load() {
    $the_slug = $_POST['slug'];
    $args=array(
      'name' => $the_slug,
      'post_type' => 'projects',
      'post_status' => 'publish',
      'showposts' => 1,
      'ignore_sticky_posts' => 1
    );
    $my_posts = get_posts($args);
    if( $my_posts ) :

        global $post;
        $post = $my_posts[0]; 
        $postCapabilityFilter = $_POST['capFilter']=='undefined' ? $_POST['capFilter'] : substr($_POST['capFilter'], 1);

        $response = json_encode( "Success" );
        header( "Content-Type: application/json" );     


$next_post = get_previous_post();
function filtered_next_post($next_post){
    if($next_post){
        $next_slug = $next_post->post_name;
        $next_ID = $next_post->ID;
        global $wpdb;
        global $postCapabilityFilter;
        $querystr = "
        SELECT $wpdb->postmeta.*
        FROM $wpdb->posts, $wpdb->postmeta
        WHERE $wpdb->posts.post_type="projects" 
        AND $wpdb->posts.post_status="publish" 
        AND $wpdb->posts.ID = $next_ID
        AND $wpdb->posts.ID = $wpdb->postmeta.post_id
        AND $wpdb->postmeta.meta_key = '_slideshow_content'
        ORDER BY $wpdb->posts.post_name DESC
        ";
        $nextProjQuery = $wpdb->get_results($querystr, OBJECT);
        foreach($nextProjQuery as $nextProj):
            $nextProjMetaArr = unserialize($nextProj->meta_value);
            foreach ($nextProjMetaArr['slides'] as $npSlideArr){
                echo 'and..';
                if ( !in_array( $postCapabilityFilter, $npSlideArr['slideCap'] ) ){
                    echo 'not in it..';
                    //$next_post = get_previous_previous_post();
                    //filtered_next_post($next_post);
                }
            }
        endforeach;                        
        return $next_slug;
    }
}
$next_slug = filtered_next_post($next_post);

3 s
3

Take a look at get_previous_post() and get_next_post() and you’ll see they both use the get_adjacent_post() to find the previous or next post.

Let’s say you want to fetch the ID of the immediately previous post based on the current post’s ID. This is what you’d do:

function get_previous_post_id( $post_id ) {
    // Get a global post reference since get_adjacent_post() references it
    global $post;

    // Store the existing post object for later so we don't lose it
    $oldGlobal = $post;

    // Get the post object for the specified post and place it in the global variable
    $post = get_post( $post_id );

    // Get the post object for the previous post
    $previous_post = get_previous_post();

    // Reset our global object
    $post = $oldGlobal;

    if ( '' == $previous_post ) {
        return 0;
    }

    return $previous_post->ID;
}

You can do a similar thing to fetch the next post’s ID … and you can do this recursively if you need to get the previous previous post:

$two_posts_ago = get_previous_post_id( get_previous_post_id( $post->ID ) );

TL;DR

Essentially, both get_previous_post() and get_next_post() reference a global $post object to do their selection. You need to set this object up before calling either function or they won’t know what post to use as a reference for next/previous.

The wrapper function above just sets up the global $post for you based on a passed-in ID. You could have it return the entire object for the previous post rather than the ID, it’s entirely up to you.

Leave a Comment