1

When I am outputting a post loop in a particular mark-up, how do I break at certain intervals, use a different mark-up for a number of next posts and then resume the loop at the appropriate point in standard layout?

Specifically...

To turn the layout on the left in to the one on the right, wherein the flow of post cards is interrupted and changed in order to introduce visual variation...

enter image description here

Note, the existing post loop for the regular whole grid of cards (left-hand example) is output as follows...

if ( $posts->have_posts() ) { ?>

    <!-- Posts row -->
    <div class="row pb-4 px-2 posts-row">
      <?php

        // Post Loop
        while ( $posts->have_posts() ) {

          $posts->the_post();

                // Regular card
                 echo '<div class="d-flex align-items-stretch col-6 col-sm-6 col-md-3 col-lg-3 col-xl-3 p-2 post-item overlay-bg">';
                 set_query_var('bgcolor',    'bg-white');
                 set_query_var('use_logo',   true);
                 set_query_var('use_byline', true);
                 set_query_var('use_source', false);
                 get_template_part('pieces/cards/post', multi);
                 echo '</div>';

        } // end while

        wp_reset_query();
      ?>
    </div><!-- end .row -->
  <?php
   } else { ?>
    Nothing here.
  <?php } ?>

But the question is not a matter of changing simply the post card CSS within the same grid (that is a challenge I already surmounted). Rather, I want to break out of the grid and re-use the alternate, above-the-fold feature block you see coloured in purple.

That block is rendered using my function display_showcase_features(), which takes as an argument a WP_Query Object containing five posts and then outputs the relevant mark-up using an alternative container grid as well as an alternative post card type.

What I need to accomplish is...

  • At post 13 in $posts
  • break the divs
  • send a WP_Query Object containing the next five posts to display_showcase_features(), which outputs the block of five posts in alternate layout
  • restore the row's opening divs
  • resume from post 18 in standard layout
  • the same at regular intervals.

I have tried the following...

if ( $posts->have_posts() ) { ?>

  <!-- Posts row -->
  <div class="row pb-4 px-2 posts-row">
    <?php

    $i=0;

      // Post Loop
      while ( $posts->have_posts() ) {

        $posts->the_post();
        $i++;

        /**
        * =======================================================
        *            VARY POST CARDS TO BREAK UP LIST
        * =======================================================
        */
        if ($i == 13 or $i == 26) { ?>
              </div><!-- end content column -->
              </div><!-- end whole row -->
              <?php display_showcase_posts($showcase_features); ?>
              <?php
              echo '<div class="container-fluid bg-light py-4">';
              echo '<div class="row pb-4 px-2 posts-row">';
               ?>
        <?php
        } else {
          /**
          * =======================================================
          *            STANDARD POST CARD LAYOUT
          * =======================================================
          */
              // Regular card
               echo '<div class="d-flex align-items-stretch col-6 col-sm-6 col-md-3 col-lg-3 col-xl-3 p-2 post-item overlay-bg">';
               set_query_var('bgcolor',    'bg-white');
               set_query_var('use_logo',   true);
               set_query_var('use_byline', true);
               set_query_var('use_source', false);
               get_template_part('pieces/cards/post', multi);
               echo '</div>';

        }

      } // end while

      wp_reset_query();
    ?>
  </div><!-- end .row -->
<?php
 } else { ?>
  Nothing here.
<?php } ?>

The mark-up interruption works fine, it's the WordPress stuff I need to learn more about...

1. How do I get a WP_Query object containing the next five posts?

In the above attempt, I am sending to display_showcase_features() merely $showcase_features, which contains the same five posts used in the above-the-fold block. But that's really only for a test.

Instead, what think I need is the next five actual posts in the standard-layout loop below. Do I need to do a new query here for some kind of range? Will that be expensive on the database?

2. How do I then elegantly resume the standard-layout loop output at the right place?

That is, in the right-hand visual example above, with the code attempt immediately above, post 13 is actually NOT rendered, because I am displaying the showcase block at that point instead. The loop should resume five posts after it was broken, assuming display_showcase_features() did output five posts.

3. How do I do this at regular intervals?

The pattern of intended layout breakage can be predicted. ie. 12 posts in standard layout, followed by sending five to display_showcase_features(), then another 12.

Though I fear that pagination could ruin things, if it might leave my divs opened, for example.

1
  1. How do I get a WP_Query object containing the next five posts? :
// $query is the original WP_Query object.

$five_posts = new WP_Query();
$five_posts->posts = array_slice(
                            $query->posts, 
                            $query->current_position, 
                            $query->current_position + 5
                        );

  1. How do I then elegantly resume the standard-layout loop output at the right place? :
/* Sum the count of all the posts you displayed with your showcase function. 

In this case they were 5, so by setting the current position to 18, the next loop iteration will 
display the post 19. */


$query->current_post += 5;
  1. How do I do this at regular intervals?:
$simple_posts_layout = 12;
$showcase_posts_layout = 5;

foreach(array_chunk($query->posts, $single_posts_layout + $showcase_posts_layout) as $chunk){
   foreach($chunk as $key => $post){
       if($key == $simple_posts_layout - 1){
           display_showcase_posts($five_posts);
           $query->current_position += $showcase_posts_layout;
           break;
       }
      $posts->the_post();
      // ... the rest of your template.
   }
}

I haven't tested the code so there might be errors, but something like this should work.

| improve this answer | |
  • This is so interesting, thanks. I am implementing the $five_posts stuff so far. However, when you array_slice the main $posts results to get five, it seems to change it from being a proper WP_Query Object, and display_showcase_features() won't output anything. The sliced thing, when print_r'd, seems to lack the [query], [query_vars], [tax_query] and [meta_query] of the original query, and only contains [posts]. Not sure why this matters, but it maybe interferes with display_showcase_features(), which uses $showcase_posts->have_posts() and $showcase_posts->the_post() – Robert Andrews Mar 28 at 12:44
  • Can you modify the display_showcase_features function? It'd make more sense to make it work over an array of WP_Post instead of a WP_Query. Also, if it uses the_post() then you don't need to manually set the current position as it is being handled already. – Himad Mar 30 at 1:03

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.