So strange result of wp_query and have_posts

I’ve tested some piece of simple code, but the result is so so strange.

Test 1:

$featured_posts = new WP_Query( $query_args );
while ($featured_posts->have_posts()) {
    $featured_posts->the_post();
    the_title(); echo '<br>';           
}
echo 'End: "' . $featured_posts->have_posts() . '"'; // have_post() is TRUE, WHY?

Test 2:

$featured_posts = new WP_Query( $query_args );
$have_posts = $featured_posts->have_posts();
while ($have_posts) {
    $featured_posts->the_post();
    the_title(); echo '<br>';           
    $have_posts = $featured_posts->have_posts();
}
echo 'End: "' . $have_posts . '"'; // false -> I think false is right.              
echo 'End: "' . $featured_posts->have_posts() . '"'; // but still TRUE, WHY?

Am I missing anything?

1 Answer
1

If we look at have_posts() in source, we can see why this happens:

function have_posts() {
    if ( $this->current_post + 1 < $this->post_count ) {
        return true;
    } elseif ( $this->current_post + 1 == $this->post_count && $this->post_count > 0 ) {
        do_action_ref_array('loop_end', array(&$this));
        // Do some cleaning up after the loop
        $this->rewind_posts();
    }

    $this->in_the_loop = false;
    return false;
}

When it reaches the end of the loop, it calls rewind_posts, which resets current_post back to -1, so the next call to have_posts will return true again.

function rewind_posts() {
    $this->current_post = -1;
    if ( $this->post_count > 0 ) {
        $this->post = $this->posts[0];
    }
}

Leave a Comment