Why is wp_reset_postdata() restarting the loop from the first post?

I’ve used the second-last example showed here:
https://github.com/scribu/wp-posts-to-posts/wiki/each_connected

The only difference is that I’ve put the_title after echoing the connected posts. So my code is:

Read More
<?php
$my_query = new WP_Query( array(
    'post_type' => 'movie'
) );

p2p_type( 'movies_to_actors' )->each_connected( $my_query, array(), 'actors' );

p2p_type( 'movies_to_locations' )->each_connected( $my_query, array(), 'locations' );

while ( $my_query->have_posts() ) : $my_query->the_post(); ?>

    <?php
    // Display connected actors
    echo '<p>Actors:</p>';

    foreach ( $post->actors as $post ) : setup_postdata( $post );
        the_title();

        ...
    endforeach;

    wp_reset_postdata();

    // Display connected locations
    echo '<p>Filming locations:</p>';

    foreach ( $post->locations as $post ) : setup_postdata( $post );
        the_title();

        ...
    endforeach;

    wp_reset_postdata();
    ?>

    <?php the_title(); ?>

<?php endwhile; ?>

The problem is that all the posts show me the title of the first post:


Actors: actors of post title n.1

Locations: locations of post title n.1

TITLE n.1


Actors: actors of post title n.2

Locations: locations of post title n.2

TITLE n.1 <<<— WRONG!!!

Related posts

2 comments

  1. wp_reset_postdata() restores the post from main query, which you do not seem to be using here at all. So before final the_title() call you jump out all the way to that post.

    Your code seems to be tad problematic to me because both your outer and inner loops continuously rewrite $post global. If you move away from that in inner loops (by using versions of functions that take post/id to act on) you will likely escape multiple overrides/resets and issues like that.

    Something like this:

    while ( $my_query->have_posts() ) : $my_query->the_post();
    
        foreach ( $post->actors as $actor ) :
    
            echo get_the_title( $actor );
    
        endforeach;
    
    endwhile;
    
  2. You actually need to globalize $post in your code for setup_postdata() to do the right thing. It’s a bit of a gotcha, as setup_postdata() merely sets up the related globals ($id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages) but doesn’t populate the global $post object, from which the_title() pulls the title.

    Solution: global $post; before your loop.

    In your case, wp_reset_postdata() isn’t really necessary since you’re never actually using the data from the main query, only the subqueries.

Comments are closed.