Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

If I have a loop running from a category query like :

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>
<ul>
<?php while ($the_query->have_posts()) : $the_query->the_post();?>
<li>.. </li><?php wp_reset_query(); ?>
<?php endwhile; ?>
</ul>

How would I create an if clause that breaks the list at a certain interval, and starts a new one. So for example at the 10th post, return a </ul> and start a new one <ul> at 11.

This is incorrect but to illustrate my objective:

<?php $count =0;
    while($count <=50){
        if ($count == 9){
            echo "<li><a href='<?php the_permalink(); ?>'>
                      <?php the_title(); ?></a></li></ul>";
            } 
        elseif ($count == 10){
        echo "<ul><li><a href='<?php the_permalink(); ?>'>
                          <?php the_title(); ?></a></li>";
        }
        else {
        echo "<li><a href='<?php the_permalink(); ?>'><?php the_title(); ?></a></li>";
        }

What is the correct way to include this logic into the loop?

share|improve this question
    
I updated my answer with something that should be generally easy to use and tested. –  hakre Feb 14 '11 at 16:13

5 Answers 5

up vote 17 down vote accepted

Create Columns for your query and easy display

In themes is probably more useful to have something that fits well into template tags and the loop. My first answer didn't focus on that much. Additionally I thought it's a bit too complicated for a quick adoption.

An easier approach that popped into my mind was to extend "the loop" with columns and came to this solution so far:

A WP_Query_Columns object "extends" any standard WP query with colums that can be easily iterated over. The first parameter is the query variable and the second parameter is the number of items to be displayed per column:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>
<?php foreach(new WP_Query_Columns($the_query, 10) as $column_count) : ?>
    <ul>
        <?php while ($column_count--) : $the_query->the_post(); ?>
        <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
        <?php endwhile; ?>
    </ul>
<?php endforeach; ?>

To use it, just add the WP_Query_Columns class from this gist to your themes function.php.

Advanced Usage

If you need the column number you're currently displaying (e.g. for some even/odd CSS classes, you can get that from the foreach as well:

<?php foreach(new WP_Query_Columns($the_query, 10) as $column => $column_count) : ?>

And the total number of columns is available as well:

<?php 
    $the_columns = new WP_Query_Columns($the_query, 10);
    foreach($the_columns as $column => $column_count) : 
?>
    <h2>Column <?php echo $column; ?>/<?php echo sizeof($the_columns); ?></h2>
    <ul>...

Twenty Ten Example

I could quickly hack twenty ten theme for a test and adding headlines above any loop this way. It's inserted into loop.php, the beginning is the theme's code:

<?php /* If there are no posts to display, such as an empty archive page */ ?>
<?php if ( ! have_posts() ) : ?>
    <div id="post-0" class="post error404 not-found">
        <h1 class="entry-title"><?php _e( 'Not Found', 'twentyten' ); ?></h1>
        <div class="entry-content">
            <p><?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'twentyten' ); ?></p>
            <?php get_search_form(); ?>
        </div><!-- .entry-content -->
    </div><!-- #post-0 -->
<?php endif; ?>

<!-- WP_Query_Columns -->
<?php 
    ### Needs WP_Query_Columns --- see http://wordpress.stackexchange.com/q/9308/178
    $query_copy = clone $wp_query; // save to restore later
    foreach( new WP_Query_Columns($wp_query, 3) as $columns_index => $column_count ) : ?>
    <ul>
        <?php 
        while ( $column_count-- ) : the_post(); ?>
            <li><h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'twentyten' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2></li>
        <?php endwhile; ?>
    </ul>       
<?php endforeach; ?>
<?php $wp_query = $query_copy;?>

<?php
    /* Start the Loop.
    ...

For a longer answer:

(that is basically how I came to the stuff above, but explains better how to actually solve the problem with simple mathematic operations. My new solution is to iterate over something pre-calculated.)

It depends a bit how much you actually need to solve the problem.

For example, if the number of items per column equals one, this is very simple:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>    
<?php while ($the_query->have_posts()) : $the_query->the_post();?>
<ul>
    <li>.. </li>
<ul>
<?php endwhile;  wp_reset_query(); ?>
</ul>

Even with that simple code, it can be seen that there are multiple decisions to be made:

  • How many items are in one column?
  • How many items are there in total?
  • Is there a new column to start?
  • And is there a column to end?

The last question is pretty interestering for HTML output as you probably want to enclose not only items but also the column with html elements.

Luckily with code, we can set all these in variables and create code that always computes to our needs.

And sometimes even, we can not even answer every question from the beginning. For exmaple, the count of total items: Are there any, some, multiple, an exact count that matches up with an integer number of columns in total?

Even Jan Fabry's answer might work in some cases (as my example above does for the one-item-per-column scenario), you might be interested in something that works for any number of items returned by WP_Query.

First for the math:

//
// arithmetical example:
//
# configuration:
$colSize = 20;  // number of items in a column
$itemsTotal = 50; // number of items (total)

# calculation:
$count = 0; // a zero-based counter variable
$isStartOfNewColum = 0 === ($count % $colSize); // modulo operation
$isEndOfColumn = ($count && $isStartOfNewColum) || $count === $itemsTotal; // encapsulation

That code doesn't run, so let's put that up into a simple text example

//
// simple-text example:
//
$column = 0; // init a column counter
for($count=0; $count<= $itemsTotal; $count++) {
    $isStartOfNewColum = 0 === ($count % $colSize); // modulo
    $isEndOfColumn = ($count && $isStartOfNewColum);
    $isStartOfNewColum && $column++; // update column counter

    if ($isEndOfColumn) {
        printf("/End of Column: %d\n", $column-1);
    }

    if ($isStartOfNewColum) {
        printf("<start of Column: %d\n", $column);
    }

    printf(" * item %d\n", $count);
}
if ($count && !$isEndOfColumn && --$count === $itemsTotal) {
    printf("/End of Column: %d\n", $column);
}

printf("Done. Total Number of Columns: %d.\n", $column);

This actually runs and does some output already:

<start of Column: 1
 * item 0
 * item 1
 * item 2
 * item 3
...
 * item 17
 * item 18
 * item 19
/End of Column: 1
<start of Column: 2
 * item 20
 * item 21
 * item 22
...
 * item 37
 * item 38
 * item 39
/End of Column: 2
<start of Column: 3
 * item 40
 * item 41
 * item 42
...
 * item 48
 * item 49
 * item 50
/End of Column: 3
Done. Total Number of Columns: 3.

This simulates already pretty well how it could look like in a wordpress template:

//
// wordpress example:
//
$count = 0; // init item counter
$column = 0; // init column counter
$colSize = 10; // column size of ten this time
$the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');
$itemsTotal = $the_query->post_count;
?>
<?php while ($the_query->have_posts()) : $the_query->the_post();?>
<?php
    # columns display variables 
    $isStartOfNewColum = 0 === ($count % $colSize); // modulo
    $isEndOfColumn = ($count && $isStartOfNewColum);
    $isStartOfNewColum && $column++; // update column counter

    if ($isEndOfColumn) {
        print('</ul>');
    }

    if ($isStartOfNewColum) {
        printf('<ul class="col-%d">', $column);
    }
?>
    <li> ... make your day ...
    </li>
<?php endwhile; ?>
<?php
if ($count && !$isEndOfColumn && --$count === $itemsTotal) {
    print('</ul>');
}
// You don't have to do this in every loop, just once at the end should be enough
wp_reset_query();
?>

(I have not executed the last example in a WP environment, but it should be at least syntactically correct.)

share|improve this answer
    
Dang. That's one heck of an answer! Lol. –  Dan Gayle Feb 14 '11 at 19:42
    
That's one epic answer for a counter, awesome! :) –  t31os Feb 15 '11 at 23:38
    
thank you! this is great :) –  zac Feb 17 '11 at 9:03
    
like something from social network lol –  Jeremy Love Mar 11 '11 at 1:20

Here is another approach you can take:

$article = 0;

<?php if (have_posts()) : ?>
    <?php while (have_posts()) : the_post(); ?>
        <?php $article = $article + 1; ?>
        <?php if ($article % 3 == 1) echo '<div class="row-fluid">';  ?>
            <div class="span4">
            <h2><a href="<?php esc_url( the_permalink() ); ?>" title="Permalink to <?php the_title(); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
            </div><!--/span-->
        <?php if ($article % 3 == 0) echo '</div><!--/row-->';  ?>
    <?php endwhile;?>
<?php else: ?>
<h2>...</h2>
<?php endif; ?>
share|improve this answer

Add the get_columns_array() function to your function.php. You can then easily iterate over your columns:

In your theme you then foreach loop over the columns:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>
<?php foreach(get_columns_array($post_count) as $column_count) : ?>
    <ul>
        <?php while ($column_count--) : $the_query->the_post(); ?>
        <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
        <?php endwhile; ?>
    </ul>
<?php endforeach; wp_reset_postdata(); ?>

I set the default size of a column to 10. You can use the second parameter to set the size of a column on your own. Like to 7: get_columns_array($post_count, 7);.

share|improve this answer

There's no need to create a separate var for counting, as the query var already counts it at: $wp_query->current_post. Also, you need to account for the final entry in the list so you don't have empty <ul></ul> in your markup.

<?php 
$the_query = new WP_Query('showposts=21&orderby=title&order=asc'); 
echo "<ul>";
while ($the_query->have_posts()) :
    $the_query->the_post();
    echo "<li>{$the_query->current_post}</li>";

    // Note that the post is already counted in the $the_query->current_post variable when in the loop. Add one to translate array counting to real counts.
    // Jan's example didn't account for the final entry in the list. Don't want empty <ul>'s hanging around
    if ((($the_query->current_post+1) % 10 == 0) && ($the_query->current_post+1 !== count($the_query->posts))):
        echo "</ul><ul>";
    endif;
endwhile;
echo "</ul>";
?>
share|improve this answer
    
Noted. Example added. –  Dan Gayle Feb 14 '11 at 23:54
    
Cool, I like the addition because the empty ´<ul></ul>` is only for 0 posts now (but for those it still is) - but from what I've learned today, that form is the smallest one w/o introducing a new function. –  hakre Feb 15 '11 at 0:50
    
Nice addition. I see that WP_Query also has a $post_count variable, you can use that instead of count($the_query->posts). Zac, you can "unaccept" my answer and accept another one if it solved your problem better. –  Jan Fabry Feb 15 '11 at 11:25
    
@Jan - I would prefer the encapsulated variable over the global one because this increases modularity. But good to know there is one. –  hakre Feb 16 '11 at 8:27

This is more a general programming question, but here is the basic idea:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>
<ul>
<?php
$post_counter = 0;
while ($the_query->have_posts()) :
    $the_query->the_post();
    $post_counter++;
?>
    <li>.. </li>
<?php
    if ( 0 == $post_counter % 10 ) {
        echo '</ul><ul>';
    }
endwhile;
?>
</ul>
<?php
// You don't have to do this in every loop, just once at the end should be enough
wp_reset_query();
?>
share|improve this answer
    
The modulo operation is basically the mathematic answer. But your example lacks semantic HTML output. I've proposed something similar in my answer, as you can imagine it took some more time ;) –  hakre Feb 14 '11 at 13:12
    
wp_reset_query(); is not related to $the_query variable. This is not needed at all, right? –  hakre Feb 14 '11 at 15:26
    
@hakre: $the_query->the_post() will overwrite the global $post variable, and wp_reset_query() restores this (by calling wp_reset_postdata() - which could also be enough on its own?). –  Jan Fabry Feb 14 '11 at 18:11
    
Okay I somehow mixed wp_query and post a bit, thought it would do something to $wp_query but $the_querywas used in the example. However, I was wrong, I'll add it to my second answer for completeness. –  hakre Feb 14 '11 at 18:21
    
You're not accounting for the last item. If the loop ends on a number divisible by 10, you will get an empty set of <ul></ul>. –  Dan Gayle Feb 15 '11 at 0:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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