The question:
I have a (relatively) tricky situation where my code requires changing the loop output every three posts, and within those three posts there are divs around two of the posts.
The code below displays 6 posts and I would want to loop though a total of 24 posts, repeating this four times.
Can anyone help? Thanks!
FIRST THREE
<div class="layer">
<div class="large left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
<div class="small left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
</div><!--layer-->
SECOND THREE
<div class="layer">
<div class="small left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
<div class="large right">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
</div><!--layer-->
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
You can do this with much less code, using the modulo
operator.
The modulo sign in PHP is %
, and works like this: it gives you the remainder of a division, for example
5 % 2 = 1
9 % 3 = 0
11 % 7 = 4
So your code would look like this (I think you have a typo in your question, in the “First Three” the second block should be labeled small right
. If I am wrong here, just edit the code below.)
For a better Overview, I start my Counter at 1, not as usual at 0, because it is easier to see which iteration is targeted by the conditionals. I also increase the counter at the last conditional – be sure you do not increment it twice!
So, before the Loop:
$counter = 1;
Then insinde the Loop:
<?php
if ( $counter % 3 == 1 ) { // use this line for the first and the fourth iteration
echo '<div class="layer">';
}
if ( $counter % 6 == 1 ) { // use this line for the first iteration only
echo '<div class="large left">';
} else if ( $counter % 6 == 2 ) { // use this line for the second iteration only
echo '<div class="small right">';
} else if ( $counter % 6 == 4 ) { // use this line for the fourth iteration only
echo '<div class="small left">';
} else if ( $counter % 6 == 5 ) { // use this line for the fifth iteration only
echo '<div class="large right">';
}
//nothing to do for the sixth and the third iteration
// the item is the same all the time
?>
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
<?php
if ( $counter % 6 == 1 || $counter % 6 == 3 || $counter % 6 == 5 || $counter % 6 == 0 ) { // use this line everytime you close a subblock
echo '</div>';
}
if ( $counter++ % 3 == 0 ) { // use this line for the third and the sixth iteration
echo '</div>';
}
?>
Method 2
I think this would work:
<?php
$counter = 1;
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div class="layer">
<?php if ($counter < 3) { ?>
<div class="large left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
<div class="small left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
<?php
$counter++;
} elseif ($counter < 6) { ?>
<div class="small left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
<div class="large right">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
<?php
$counter++;
} else {
$counter = 0;
}
?>
</div><!--layer-->
?>
Set a counter, if the loop is less than 3, do the first option, elseif the loop is less than 6 do the second option, else, reset the counter
Method 3
I think this may work, might need some refinement:
<?php if ($counter == 1){ ?>
<div class="layer">
<div class="large left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
<?php } elseif ($counter == 2){ ?>}
<div class="small left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
<?php } elseif ($counter == 3){ ?>}
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div><!--end small left-->
</div><!--end layer-->
<?php } elseif ($counter == 4){ ?>}
<div class="layer">
<div class="small left">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--end item-->
<?php } elseif ($counter == 5){ ?>}
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div><!--end small left-->
<?php } elseif ($counter == 6){ ?>}
<div class="large right">
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
</div>
</div><!--layer-->
<?php }
$counter++;
if (($wp_query->current_post + 1) == ($wp_query->post_count)) {
switch($counter){
case 1:
echo '</div><!--end layer-->';
break;
case 2:
echo '</div><!--end small left-->
</div><!--end layer-->';
break;
case 3:
break;
case 4:
echo '</div><!--end small left-->
</div><!--end layer-->';
break;
case 5:
echo '</div><!--end layer-->';
break;
case 6:
break;
default:
break;
}
}
endwhile;?>
Method 4
For reference, someone on another forum achieved the same correct output slightly differently (although using the same principles…). Thanks to both!
<?php
while( have_posts() ) : the_post();
$position = $wp_query->current_post;
$p3 = $position%3;
$p6 = $position%6;
$number_posts = $wp_query->post_count-1;
if( $p3 == 0 ) echo '<div class="layer">';
if( $p6 == 0 ) echo '<div class="large left">';
elseif( $p6 == 1 || $p6 == 3) echo '<div class="small left">';
elseif( $p6 == 5 ) echo '<div class="large right">'; ?>
<div class="item">
<?php the_title(); ?>
<?php the_content(); ?>
</div><!--item-->
<?php if( $position == $number_posts || in_array($p6, array(0, 2, 4, 5)) ) echo '</div>';
if( $p3 == 2 || $position == $number_posts ) echo '</div><!--layer-->';
endwhile; ?>
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0