WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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'];
      '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){
        $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();
        return $next_slug;
$next_slug = filtered_next_post($next_post);
share|improve this question
up vote 6 down vote accepted

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:

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 ) );


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.

share|improve this answer
This is actually the approach I started with, but for some reason everything would lock up when I tried to return $post to the $oldpost. No errors, no indication of what was going wrong, just a spinning loading gif. Probably something wacky with my code, but I couldn't for the life of me figure it out. Now my code is pretty much working but its a beast of SQL querires and took several hours to put together. – Zach Lysobey Jun 15 '12 at 3:30

Here, you can get adjacent post for specific post type with custom sql query & with filter get_{$adjacent}_post_where where default adjacent is previous. Also result depends on $current_post_date & comparison operator $op.

function bm_get_adjacent_post( $post_id, $author_id, $previous = 1 ) {
global $wpdb;

if ( ( ! $post = get_post( $post_id ) )  )
    return null;

$current_post_date = $post->post_date;

$adjacent = $previous ? 'previous' : 'next';
$op = $previous ? '<' : '>';
$order = $previous ? 'DESC' : 'ASC';

$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare( "WHERE  p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' AND p.post_author = %d", $current_post_date, 'projects' , $author_id ), '', '' );
$sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );

$query = "SELECT p.ID FROM $wpdb->posts AS p $where $sort";
//echo $query;
$result = $wpdb->get_var( $query );
if ( null === $result )
    $result = '';
if ( $result )
    $result = get_post( $result );

return $result;
share|improve this answer
This is not an answer. Please add an explanation to what your code does and how it works. – Pieter Goosen May 13 '14 at 7:02
That's better. Thanks – Pieter Goosen May 13 '14 at 8:30

Your Answer


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.