Close loop if no new item exists

I have created a WordPress loop that that wraps wraps a div around every 3 sets of blog posts. Essentially, it outputs like this:

<div class="row"> // This row does have 3 sets of columns, so it will create another row
    <div class="large-4 medium-4 columns panel grid">
        <--Content Stuff-->
    </div>
    <div class="large-4 medium-4 columns panel grid">
        <--Content Stuff-->
    </div>
    <div class="large-4 medium-4 columns panel grid">
        <--Content Stuff-->
    </div>
</div>
<div class="row"> // Since this row doesn't have three sets of columns, so it does not create another row
    <div class="large-4 medium-4 columns panel grid">
        <--Content Stuff-->
    </div>
    <div class="large-4 medium-4 columns panel grid">
        <--Content Stuff-->
    </div>
</div>

However, I run into issues when I have 3, 6 or 9 blog posts as the loop is creating a new div but has no content to fill it with.

Read More

Here is what I currently have – which is working great except for the issue noted above:

<div class="row" data-equalizer>

    <?php $i = 1; ?>
    <?php query_posts; ?>
    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
    <?php if ($community_posts->have_posts()) : while ($community_posts->have_posts()) : $community_posts->the_post(); ?>

<div class="large-4 medium-4 columns" data-equalizer-watch>
    <?php get_template_part( 'partials/loop', 'archive-grid' ); ?> // This is the WP Loop
    <?php if ($counter % 3 == 0){echo '</div><div class="row" data-equalizer>';} ?>
    <?php $counter++ ; endwhile; echo '</div>'; ?>
</div>      

<?php else : ?>

    <?php get_template_part( 'partials/content', 'missing' ); ?>

<?php endif; ?>

How can I tell the loop to end if a new item does not exist?

Related posts

Leave a Reply

6 comments

  1. You can use the following built-in properties of the WP_Query() class:

    WP_Query::current_post // Index of the current post, starts at 0
    WP_Query::found_posts  // The total number of posts found
    WP_Query::post_count   // The number of posts being displayed.
    

    to make your life eaiser, instead of introducing custom counters.

    Here’s an example that works on my install:

    <?php $q = new WP_Query( array( 'posts_per_page' => 6 ) ); // Edit your query ?>
    
    <?php if( $q->have_posts() ) : ?>
    
        <?php while ( $q->have_posts() ) : $q->the_post(); ?>
    
            <?php if( 0 === ( $q->current_post  )  % 3 ): ?>
                <!--Begin Row:--> <div class="row" data-equalizer>
            <?php endif; ?> 
    
            <!--Item: -->
            <div class="large-4 medium-4 columns" data-equalizer-watch>
                <?php get_template_part( 'partials/loop', 'archive-grid' ); ?> 
            </div>
    
            <?php if( 0 === ( $q->current_post + 1 )  % 3  ||  ( $q->current_post + 1 ) ===  $q->post_count ): ?>
                <!--End Row: --> </div>
            <?php endif; ?>
    
        <?php endwhile; ?>
        <?php wp_reset_postdata(); ?>
    
    <?php else : ?>
    
        <?php get_template_part( 'partials/content', 'missing' ); ?>
    
    <?php endif; ?>
    

    This should give you the following layouts with three items per row:

    #posts: 1
    <div class="row" data-equalizer>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
    </div>
    
    #posts: 2
    <div class="row" data-equalizer>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
    </div>
    
    #posts: 3
    <div class="row" data-equalizer>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
    </div>
    

    and

    #posts: 4
    <div class="row" data-equalizer>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
    </div>
    <div class="row" data-equalizer>
        <div class="large-4 medium-4 columns" data-equalizer-watch>
            <--Content Stuff-->
        </div>
    </div>
    

    and so on.

  2. I do not use WordPress, but essentially in the if statement you need to check that the next post exists. Change the if statement to:

     <?php if ($counter % 3 == 0 && have_posts()){echo '</div><div class="row" data-equalizer>';} ?>
    

    Assuming that have_posts() returns whether the next post exists.

  3. Try this code below. Code is not tested. So might need some adjustments.

    $args = array(
        'posts_per_page' => 10
    );
    
    $query = new WP_Query($args);
    
    $i = 0;
    
    if( $query->have_posts() ): while($query->have_posts()): $query->the_post();
    
        echo ($i%3 == 0) ? '<div class="row">' : '';  // start the row
    
        ?> 
    
        <div class="large-4 medium-4 columns panel grid">
            <--Content Stuff-->
        </div>
    
        <?php 
        echo ( ($i+1)%3 == 0 ) ? '</div>' : ''; // end the row
    
    $i++;
    
    endwhile; endif;
    
    // for the cases we get out of the loop without ending the </div>, ie: $post_count != 3,6,9.. etc
    $post_count = $query->post_count;
    
    if($post_count%3 != 0)
        echo '</div>';
    
  4. Since I’ve had the need for something like this several times, I was always trying to solve this by using the counter and modulus operator. This question gave me an interesting idea, that it would be useful to have a custom type of loop that will work with chunks of posts.

    This function manipulates $wp_query object by changing the post_count and current_post properties and thus controls what will be displayed in the loop. It behaves similar as the have_posts() function.

    function have_chunks( $items, $query = null ) {
        global $wp_query;
        global $chunks;
    
        $query = isset( $query ) ? $query : $wp_query;
    
        if ( !isset( $chunks ) ) {
            if ( $query->post_count ) {                 
                $chunks = array_chunk( array_keys( $query->posts ), $items );
                $query->post_count = end( current( $chunks ) ) + 1;
    
                return true;
            }
            return false;
    
        } elseif ( key( $chunks ) + 1 < count( $chunks ) ) {
            $query->current_post = current( next( $chunks ) ) - 1;
            $query->post_count = end( current( $chunks ) ) + 1;
    
            return true;
    
        } elseif ( key( $chunks ) + 1 === count( $chunks ) ) {
            unset( $chunks );
    
        }
    
        return false;   
    
    }
    

    Usage in main loop:

    <?php if ( have_posts() ) : ?>
    
        <?php while ( have_chunks( 3 ) ) : ?> 
    
            <div class="row">
    
            <?php while ( have_posts() ) : the_post(); ?>
    
                <div class="large-4 medium-4 columns panel grid">
    
                    <?php get_template_part( 'partials/loop', 'archive-grid' ); ?>
    
                </div>
    
            <?php endwhile; ?>      
    
            </div>
    
        <?php endwhile; ?>
    
    <?php endif; ?> 
    

    Usage with custom $wp_query object:

    <?php
    
    $query = new WP_Query( array( 'posts_per_page' => -1 ) );
    
    ?>
    
    <?php if ( $query->have_posts() ) : ?>
    
        <?php while ( have_chunks( 3, $query ) ) : ?> 
    
            <div class="row">
    
            <?php while ( $query->have_posts() ) : $query->the_post(); ?>
    
                <div class="large-4 medium-4 columns panel grid">
    
                    <?php get_template_part( 'partials/loop', 'archive-grid' ); ?>
    
                </div>
    
            <?php endwhile; ?>      
    
            </div>
    
        <?php endwhile; ?>
    
    <?php endif; ?>
    
  5. Right now you’re starting a row before you begin your loop, then ending and starting a new row after cell multiples of three (pseudocode):

    start new row
    begin loop of cells with counter
        output cell
        if cell is multiple of 3
            end row
            start new row
    end loop
    end row
    

    You’re having an extra row created because you’re testing to see whether you should end/start rows after you output the cell — if you shift that test to before the cell, you’ll be fine:

    begin loop of cells with counter
        if cell is a multiple of 3        // cells 0, 3, 6, etc
            if cell is not the first
                end row
            start new row
    
        output cell
    end loop
    end row
    

    Make sense? Your actual code would need to be the following (replacing the entire snippet above):

        <?php $i = 0; ?>
        <?php query_posts; ?>
        <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
        <?php if ($community_posts->have_posts()) : while ($community_posts->have_posts()) : $community_posts->the_post(); ?>
    
        <?php 
        if ($counter % 3 == 0) { 
            if ($counter != 0) {
                echo '</div>';
            }
            echo '<div class="row" data-equalizer>';
        } ?>
    
    <div class="large-4 medium-4 columns" data-equalizer-watch>
        <?php get_template_part( 'partials/loop', 'archive-grid' ); ?> // This is the WP Loop
        <?php $counter++ ; endwhile; echo '</div>'; ?>
    </div>      
    
    <?php else : ?>
    
        <?php get_template_part( 'partials/content', 'missing' ); ?>
    
    <?php endif; ?>