2

I'm missing something here. What's the proper way to reset a query so that it doesn't interfere with any other queries it may be nested in?

This is the kind of result I'm going for:

Main page

This is the main page content. Now let's display some custom nested queries.

Outer page 1

 Inner post 1
 Inner post 2

Outer page 1 content continued...

Outer page 2

 Inner post 1
 Inner post 2

Outer Page 2 content continued...

...etc.

But I can't get the Outer Page X content continued part working—it always reverts to either the inner query or the main page query.

Here's my page template. It's commented with the behavior I get with each of the reset functions (wp_reset_postdata(), wp_reset_query(), $query->reset_query(), and $query->reset_postdata()).

// BEGIN PAGE TEMPLATE 

while ( have_posts() ) : the_post();

    the_title(); // "Main page"

    /* --------- OUTER QUERY --------- */
    $outer_query = new WP_Query( [ 'post_type' => 'page' ] );

    if ($outer_query->have_posts()) : 
        while ($outer_query->have_posts()) : $outer_query->the_post();
            the_title(); // "Outer page 1", "Outer page 2", etc.

                /* --------- INNER QUERY --------- */
                $inner_query = new WP_Query( [ 'post_type' => 'post', 'posts_per_page' => 2 ] ); 

                if ($inner_query->have_posts()) :
                    while ($inner_query->have_posts()) : $inner_query->the_post();
                        the_title();
                    endwhile;
                endif;

            /**
             * Now I'm done with the inner query.
             * How do I get back to the outer query?
             * 
             * Desired value of the_title(): 
             *   "Outer page 1" on first iteration, "Outer page 2" on second, etc.
             */

            // wp_reset_postdata();            // Nope! Results in "Main page"
            // wp_reset_query();               // Nope! Results in "Main page" 
            // $inner_query->reset_postdata(); // Nope! Results in "Inner post 1"
            // $inner_query->reset_query();    // Nope! Results in "Inner post 2"
            // If no reset is used:            // Nope! Results in "Inner post 2"
            the_title();

        endwhile;
    endif;
    wp_reset_postdata();

    // Now back to the main page
    the_title(); // Works

endwhile;

// END OF PAGE TEMPLATE

What's the proper way to do this? I'm looking for a generalizable answer that doesn't rely on knowing how many levels deep the query is, or the context in which it's being used. i.e., something that could be extracted into a shortcode.

2
  • If you're trying to reset it to $outer_query, I think you want $outer_query->reset_postdata();, that's the query object that holds the $post data that you want.
    – Milo
    Commented Apr 28, 2017 at 21:37
  • If the ultimate goal of this is to be able to create a shortcode that doesn't pollute $post, then use get_posts, a foreach loop, and template tags that can be passed a post ID, and eliminate the need to worry about this entirely.
    – Milo
    Commented Apr 28, 2017 at 21:42

1 Answer 1

1

This touches upon an answer provided here Loop within a loop? except I posted the full code:

$query = new WP_Query($args);

while ($query->have_posts()) :

    // initialization for $inner_args & backup the current global $post
    global $post;
    $backup = $post; 
    $inner_query = new WP_Query($inner_args);

    while ($inner_query->have_posts()) :
        // do something
    endwhile;
    $inner_query->reset_postdata();
    // restore the global $post from the previously created backup
    $post = $backup;

endwhile;
$query->reset_postdata();

The important thing here is you are setting the current post as a backup, because when the inner nested WP_Query postdata is set up, the prior loop's is lost. After the inner query finishes looping, you can set the post back to your backup and continue in the "parent" loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.