0

I have a page template that has the following:

<?php get_template_part( 'include', 'certifications-popular' ); ?>

Within this file, I have two loops. But having the second loop in there seems to break everything (and nothing is output from either of the loops).

Whereas if I remove the second loop, then the lines of <p>TEST</p> are output just fine:

<h2>Popular standards</h2>
<div class="row">
    <div class="col-12">

    <?php query_posts('post_type=page&post_parent=27&posts_per_page=-1&orderby=menu_order&order=ASC'); ?>
    <?php if ( have_posts() ) : ?>
        <?php while ( have_posts() ) : the_post(); ?>

            <p>TEST</p>

        <?php endwhile; ?>

        <?php endif; ?>
        <?php wp_reset_query(); ?>

    </div>
</div>

<h3>Other standards</h3>
<div class="row">
    <div class="col-12">
    <?php query_posts('post_type=page&post_parent=27&posts_per_page=-1&orderby=menu_order&order=ASC'); ?>
    <?php if ( have_posts() ) : ?>
        <?php while ( have_posts() ) : the_post(); ?>

                <p>TEST</p>

        <?php endwhile; ?>
    <?php wp_reset_query(); ?>
    </div>
</div>

Ignore the fact that the queries are the same, I will eventually add some if statements within the loops to display what I need in each.

  • 2
    Have you tried using WP_Query() instead? It's generally encouraged while query_posts() is typically discouraged. – WebElaine May 29 at 14:27
  • 2
    I would strongly advise against using query_posts, it causes a lot of problems, always use a standard WP_Query loop instead. In the meantime take a look at your PHP error log to see what the error message was ( also hey Matt! ) – Tom J Nowell May 29 at 14:40
1

The root problem here is a missing endif; on the second loop.

But, there are a few changes we can make to improve this and make things work, this loop, will work a lot better:

<h3>Other standards</h3>
<div class="row">
    <div class="col-12">
    <?php
    $query = new WP_Query( [
        'post_type'      => 'page',
        'post_parent'    => 27,
        'posts_per_page' => 100,
        'orderby'        => 'menu_order'
        'order'          => 'ASC'
    ] );
    if ( $query->have_posts() ) {
        while ( $query->have_posts() ) {
            $query->the_post();
            ?>
            <p>TEST</p>
            <?php
        }
        wp_reset_postdata();
    }
    ?>
    </div>
</div>
  • switched from query_posts and wp_reset_query to WP_Query, pretend query_posts doesn't exist, it causes more issues than it solves and WP_Query is superior in every way
  • Added a wp_rest_postdata inside the if statement after the while loop, now we only cleanup things when there are things to cleanup
  • replace the parameter string with an array of keys and values, a minor optimisation but now no string parsing takes place, are numbers are numbers rather than strings, and we can use more complex parameters such as tax_query etc
  • set posts_per_page to a high value rather than unlimited, sure you might only have 20 or 70 pages, but what if you import a tonne by accident or business requirements change? It's better to set an unrealistically high number that you know the page and server can handle as the worst case scenario. Fetching more than 100 posts at a time isn't a good idea, if you need more than 100, consider putting a link to a post archive.
  • I removed the extra PHP opening and closing tags for blocks of PHP that have no template tags inbetween them, this should make the original mistake a lot easier to spot
  • By doing it this way, if you've set an opentype font in your editor you'll get lovely ligatures for the -> and => syntax
  • You could put that array in a variable, then if you needed a 3rd loop you could just change the bit you want instead of creating a new array from scratch

I'd also consider removing the hardcoded post parent number, as the template will break on a site migration using the WP importer, or if that page is deleted and recreated. It also means if you need to set up the site again or locally this template won't work

So instead here are 3 alternatives:

  • use named pages, and fetch the post via its slug to get the ID, this solves the problem of hardcoded numbers
  • use the children of a named page, this would let you wrap this all in another query loop and automate the titles, adding new pages would add new sections
  • A standards post type with a category taxonomy. Then you could just loop over the terms and query the posts, and you'd get a free paginated archive and URLs
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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