0

I'm using WP_Query to get all pages without subpages. For each page I'm using again WP_Query to get all child pages of the current page inside the first loop.

This all works fine and I'm getting the expected result.

But when now using a third WP_Query on one of the sub pages, the second level loop breaks.

I already tried the functions wp_reset_query() and wp_reset_postdata() but they didn't do the trick.

Also I tried to save the global $wp_query and global $post and reset them after the loop, but this didn't help too.

How do I implement nested queries in WP?

Edit As requested (and how it would have been correct) here is my code. I also realized that my problem does not apply only to the third, but also to the second loop.

$all_pages = new WP_Query(array('post_type' => 'page', 'post_status' => 'publish', 'post_parent' => 0));

while($all_pages->have_posts()) {
    $all_pages->the_post();
    include(get_page_template());
}

wp_reset_postdata();

In the page templates I'm using the following code to get child pages:

// child page content rendered here, depending on template

if($post->post_parent == 0) {
    $child_pages = new WP_Query(array('post_type' => 'page', 'post_status' => 'publish', 'page_parent' => $post->post_parent));

    while($child_pages->have_posts()) {
        $child_pages->the_post();
        include(get_page_template());
    }

    wp_reset_postdata();
}

I can execute WP_Queries on the child pages. But when then using the_post(); the $child_page loop stops executing.

3
  • 4
    Please show your complete loop instead of just a description of it.
    – kaiser
    May 16, 2014 at 21:35
  • I will provide it later this evening, when I'm back in office. May 18, 2014 at 13:25
  • 2
    you should use get_template_part not include to pull in template files
    – Tom J Nowell
    May 19, 2014 at 13:16

2 Answers 2

2

This can be done in a single query:

$parent_only = new WP_Query( array(
    'post_parent' => 0,
) );

If you want to have all children of a specific page (for e.g.) in the loop (or on a request that returns TRUE for is_singular()), use get_the_ID() as argument for post_parent.

Edit (after seeing the full loop in the updated question)

The get_page_template() function should be used in the template_include filter callback. When you look at ~/wp-includes/template-loader.php and its internals, then you will see the following:

is_page() && $template = get_page_template()

This function is not meant to be used inside templates. When you want to include template parts, then stick with get_template_part() instead.

I assume you want to build a list of pages where each child page is listed below the parent page - and each child-child page is listed below the parent page. This can be done with wp_list_pages() Source:

<ul>
    ?>
    wp_list_pages( array(
        'title_li' => sprintf(
            '<h2>%s</h2>'
            __( 'Pages sorted by parent', 'your-textdomain' )
        ),
    ) );
    <?php
</ul>

Now this will just output a list of pages. When you look closer at the list of arguments, then you can use: child_of and echo as well:

// Get all parent pages:
$pages = get_pages( array(
    'number' => 0, // get *all* pages
) );

// Container:
$output = array();
// Loop and fetch
foreach ( $pages as $page )
{
    $output[] = wp_list_pages( array(
        'title_li' => '...',
        'echo'     => false,
        'child_of' => $page->ID,
    ) );
}

// Build the output:
foreach ( $output as $p )
    // etc.

Above example is just meant to clarify internals. Of course you can simply adjust the depth argument, so wp_list_pages() fetches parents and their children to build an unordered HTML list.

So the correct approach would be to pass in the needed depth and if you need custom ordering, then go with a custom walker assigned to the walker-key.

Summed up - core does it for you per default.

9
  • You can just use this code from @kaiser in several foreach loops.
    – Baerkins
    May 17, 2014 at 2:48
  • I'm actually not doing anything else. And as I stated in the OP, it kind of works. Only when using a third query, it breaks the loop... I will provide my code when I'm back in office May 18, 2014 at 13:24
  • @Julian Please edit your question and show your COMPLETE loop !
    – kaiser
    May 18, 2014 at 13:25
  • @kaiser read my comment, I already stated to do so ;-) May 19, 2014 at 0:08
  • I don't see any loop in your question ... just a description...
    – kaiser
    May 19, 2014 at 0:45
1

I just found the answer. I think I had another issue anywhere so my real problem could not be solved. I did it like this:

In the page templates at first I'm doing

global $post;
$saved_post = $post;

and at the end of the page templates this:

if($saved_post) {
    $post = $saved_post;
}

I have two files (page.header.php and page.footer.php) which I include in every single page template, which do the save and restore.

There might be a better solution, so I'm still happy with answers and ideas :-)

0

Your Answer

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

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