Resetting post data to previous loop in nested loops

I’m trying to use nested loops with the posts to posts plugin. The loops both work, but the problem arises after the second nested loop ($issue). I want to access the $publication loop again, but the data is still the $issue data.

wp_reset_query() will reset right back to the main loop in single.php which I don’t want.

Read More

I could use get_posts() instead of new WP_Query, but I want to be able to use get_template_part().

How can I reset my data back to the publication loop, so that the second ‘Publication title’ returns the publication, not the issue, title?

Here’s my code within single.php:

$publication = new WP_Query( array(
'connected_type'  => 'publication_to_post',
'connected_items' => $post->ID,
'fields'          => 'ids',
'posts_per_page'  => 1,
) );

if ( $publication->have_posts() ) {
while ( $publication->have_posts() ) : $publication->the_post();
    echo '<h2>Publication title = '.get_the_title().'</h2>';
    $pub_id = get_the_ID();

    $issue = new WP_Query( array(
        'connected_type'  => 'publication_to_issue',
        'connected_items' => $pub_id,
        'fields'          => 'ids',
        'posts_per_page'  => 1,
    ) );

    if ( $issue->have_posts() ) {
        while ( $issue->have_posts() ) : $issue->the_post();

            // need to be able to use template parts in here
            echo '<h2>Issue title = '.get_the_title().'</h2>';

        endwhile;
    }

    // This currently returns the issue title, not the publication title
    echo '<h2>Publication title = '.get_the_title().'</h2>';

endwhile;
}

Related posts

2 comments

  1. I’m going to answer this myself, but it was the very clever @simonwheatley of Code for the People that solved this one for me.

    Instead of using wp_reset_postdata() or wp_reset_query(), you can use the following:

    $publication->reset_postdata();
    

    Where $publication is your query object.

    The working code now looks like:

    $publication = new WP_Query( array(
    'connected_type'  => 'publication_to_post',
    'connected_items' => $post->ID,
    'fields'          => 'ids',
    'posts_per_page'  => 1,
    ) );
    
    if ( $publication->have_posts() ) {
    while ( $publication->have_posts() ) : $publication->the_post();
        echo '<h2>Publication title = '.get_the_title().'</h2>';
        $pub_id = get_the_ID();
    
        $issue = new WP_Query( array(
            'connected_type'  => 'publication_to_issue',
            'connected_items' => $pub_id,
            'fields'          => 'ids',
            'posts_per_page'  => 1,
        ) );
    
        if ( $issue->have_posts() ) {
            while ( $issue->have_posts() ) : $issue->the_post();
    
                // need to be able to use template parts in here
                echo '<h2>Issue title = '.get_the_title().'</h2>';
    
            endwhile; $publication->reset_postdata();
        }
    
        echo '<h2>Publication title = '.get_the_title().'</h2>';
    
    endwhile;
    }
    
  2. First of all, I think it’s possible to use get_posts() in combination with setup_postdata(). With these, you can use the template tags as in a normal WordPress loop.

    But you can use this function also in your nested loops:

    # make sure $post is the global in your scope (which should be the case in single.php)
    global $post;
    if ( $publication->have_posts() ) {
    while ( $publication->have_posts() ) : $publication->the_post();
        echo '<h2>Publication title = '.get_the_title().'</h2>';
        $pub_id = get_the_ID();
    
        # preserve the current post in the higher loop
        $preserve_post = get_post();
    
        $issue = new WP_Query( array(
            'connected_type'  => 'publication_to_issue',
            'connected_items' => $pub_id,
            'fields'          => 'ids',
            'posts_per_page'  => 1,
        ) );
    
        if ( $issue->have_posts() ) {
            while ( $issue->have_posts() ) : $issue->the_post();
    
                // need to be able to use template parts in here
               echo '<h2>Issue title = '.get_the_title().'</h2>';
    
            endwhile;
        }
    
        # set the global back to your first loop post
        $post = $preserve_post;
        setup_postdata( $post );
        // This currently returns the issue title, not the publication title
        echo '<h2>Publication title = '.get_the_title().'</h2>';
    
    endwhile;
    }
    wp_reset_query();
    

Comments are closed.