Changing HTML structure according to counter - php

I have an HTML structure that I need to dynamically output.
I am using a counter within my loop to check for the first post, and applying the class headline-big and m-grid-item for the first post. Then I'm applying the second class headline-scroll for the subsequent posts.
The problem is, the 2nd, 3rd and 4th posts are not being nested inside headline-scroll they are each getting their own div.headline-scroll which is messing up site.
I need the 2nd, 3rd and 4th posts to be nested inside a single div.headline-scroll instead of each one of them being nested under a separate one.
This is the HTML for structure
<!-- / 1ST POST -->
<div class="headline-big">
<div class="m-grid-item">
...
</div>
</div>
<!-- / END OF FIRST POST -->
<!-- / 2ND, 3RD AND 4TH POST - ALL NESTED INSIDE div.headline-scroll -->
<div class="headline-scroll">
<!-- / 2ND POST -->
<div class="m-grid-item -medium">
...
</div>
<!-- / END OF 2ND POST -->
<!-- / 3RD POST -->
<div class="m-grid-item -small">
...
</div>
<!-- / END OF 3RD POST -->
<!-- / 4TH POST -->
<div class="m-grid-item -small">
...
</div>
<!-- / END OF 4TH POST -->
</div>
And this is the PHP
if ( $featured->have_posts() ) {
$i = 0;
while ( $featured->have_posts() ) {
$featured->the_post();
if ( $i == 0 ) :
?>
<div class="headline-big">
<div class="m-grid-item">
<?php endif; ?>
<?php if ( $i != 0 ) : ?>
<div class="headline-scroll">
<div class="m-grid-item -medium">
<?php endif; ?>
<?php the_title(); ?>
</div>
</div>
<?php $i++;
}
} else {
echo 'Add some posts';
}

I'm not sure if I could be able to answer your question well. But this is how I understand. If there is a question, please let me know and I will modify.
if ( $featured->have_posts() ) {
$i = 1;
while ( $featured->have_posts() )
{
$featured->the_post();
if( $i == 1)
{
?>
<div class="headline-big">
<div class="m-grid-item">
<?php the_title(); ?>
</div>
</div>
<div class="headline-scroll">
<?php
}
else
{
$small = array(3,4); //list of small classes
$class = ( in_array($i, $small)) ? '-small' : '-medium';
<div class="m-grid-item <?php echo $class; ?>">
<?php the_title(); ?>
</div>
<?php
}
$i++;
}
echo '</div><!-- end of headline-scroll -->';
} else {
echo 'Add some posts';
}

I've simplified it here with if conditions.
If it's the first post, create the headline-big div.
If it's the second post, create the headline-scroll div and the medium class div.
For all subsequent posts, just use the small div. Finally, outside the while loop, if we had more than 1 post, we need to add a closing div to close off the headline scroll.
if ( $featured->have_posts() ) {
$i = 0;
while ( $featured->have_posts() )
{
$featured->the_post();
if( $i == 0)
{
?>
<div class="headline-big">
<div class="m-grid-item">
<?php the_title(); ?>
</div>
</div>
<?php
}
else if($i == 1)
{
?>
<div class="headline-scroll">
<div class="m-grid-item -medium">
<?php the_title(); ?>
</div>
<?php
}
else
{
<div class="m-grid-item -small">
<?php the_title(); ?>
</div>
}
$i++;
}
if($i > 1){
?>
</div><!-- end of headline-scroll -->
<?php
}
} else {
echo 'Add some posts';
}

You never closed many of your DIV tags, and you were opening your div.headline-scroll inside a loop, so you were bound to get more than one. Try this instead maybe? Consistent indent and minimal PHP in your HTML will make things easier to debug, though you're hamstrung by Wordpress' awful functions.
<?php if (!$featured->have_posts()):?>
<p>Add some posts!</p>
<?php else: $i = 0; while ($featured->have_posts()): $featured->the_post();?>
<?php if (!$i):?>
<div class="headline-big">
<div class="m-grid-item">
<?php the_title(); ?>
</div>
</div>
<div class="headline-scroll">
<?php else:?>
<div class="m-grid-item -medium">
<?php endif; ?>
<?php the_title(); ?>
</div>
<?php $i++; endwhile;?>
</div>
<?php endif?>

Related

Running three iterations on a foreach loop

I am running a listing on a page in a row with three columns each. Each column requires different classes, I need to find a way to return these classes in a foreach loop to achieve the following ...
<div class="row">
<div class="box_skin1">...</div>
<div class="box_skin2">...</div>
<div class="box_skin3">...</div>
<div class="box_skin1">...</div>
<div class="box_skin2">...</div>
<div class="box_skin3">...</div>
</div>
I am currently using the following for alternating rows but now need to add a third ... how do I do that?
<?php $counter = 1; ?>
<div class="row">
<?php foreach ($newsRecords as $record): ?>
<?php if($counter % 2) : ?>
<!-- ROW 1 -->
<div class="box_skin1">...</div>
<?php else : ?>
<!-- ROW 2 -->
<div class="box_skin2">...</div>
<?php endif; ?>
<?php $counter++; ?>
<?php endforeach ?>
</div>
This should work
EDITED
<?php $counter = 1; ?>
<div class="row">
<?php foreach ($newsRecords as $record): ?>
<?php if($counter % 3 == 0) : ?>
<!-- ROW 3 -->
<div class="box_skin3">...</div>
<?php elseif ($counter % 3 == 2) : ?>
<!-- ROW 2 -->
<div class="box_skin2">...</div>
<?php elseif ($counter % 3 == 1): ?>
<!-- ROW 1 -->
<div class="box_skin1">...</div>
<?php endif; ?>
<?php $counter++; ?>
<?php endforeach ?>
</div>
IF-ELSE free structure. If you plan to add new div then you dont have to add new else-if condition just you need to increase counter size and it will work.
<?php $counter = 1; ?>
<div class="row">
<?php foreach ($newsRecords as $record): ?>
<div class="box_skin<?php echo $counter; ?>">...</div>
<?php
$counter++;
if ($counter >= 3) {
$counter = 1;
}
?>
<?php endforeach ?>
</div>

PHP Product Listing - End of Loop Close Row

Sorry for the title, I wasn't sure how to word it.
Basically, I have a webpage that uses Advanced Custom Fields to populate products, it loops through the products and displays them in groups of three, per row; each row alternates color - light grey to dark grey.
My issue is, the code I wrote is checking if each row has 3 items, so if the product listing row ends on 1 or 2, the row containing div is not closed off, thus wrapping my footer and messing up the for the rest of the page. The following is my code, it should be pretty easy to follow - you can also see I am using LazyLoadAny - Basically, I count the items, if there are more than 6 I lazyload the rest. On the first item I open the row container and when there are three I close it. So again, I need to figure out how to close the container if the row ends on 1 or 2 items not just 3.
Short Version: How do I close the "internal-product-light" or "internal-product-dark" rows if they end with 1 or 2 products instead of 3?
<?php
$count = 0;
$rowCount = 0;
$rowClass = "internal-product-light";
// check if the repeater field has rows of data
if( have_rows('product_listing_repeater') ): ?>
<div class="internal-container">
<div class="full-product-line-contain">
<?php // loop through the rows of data
while ( have_rows('product_listing_repeater') ) : the_row(); $count++; $rowCount++; ?>
<?php if($rowCount == 1) { ?>
<div class="<?php echo $rowClass; ?>">
<div class="product-centering">
<?php if($count > 6) { ?>
<div class="js-lazyload">
<?php echo "<!--"; }
} ?>
<div class="internal-section product-line-item product-alignment clearfix">
<div class="product-contain">
<?php if(get_sub_field('has_link')): ?>
<a href="<?php the_sub_field('link_url')?>" class="product-link">
<?php
if(get_sub_field('has_image')):
$singleImage = get_sub_field('block_image');
?>
<img class="product-line-image" src="<?php echo $singleImage ?>" />
<?php endif; ?>
</a>
<?php endif; ?>
<div class="internal-content-contain-right no-float">
<?php if(get_sub_field('has_link')): ?>
<a href="<?php the_sub_field('link_url')?>" class="product-link-title">
<h2><?php the_sub_field('block_headline'); ?></h2>
</a>
<?php endif; ?>
<?php if(get_sub_field('has_link')): ?>
<?php the_sub_field('link_text')?>
<?php endif; ?>
</div>
</div>
</div>
<?php if($rowCount == 3) { ?>
<?php if($count > 6) { echo "-->"; ?>
</div><!-- End lazy load div -->
<?php } ?>
</div><!-- End product centering -->
</div><!-- End row -->
<?php $rowCount = 0;
if($rowClass == "internal-product-light"){ $rowClass = "internal-product-dark";}else{$rowClass = "internal-product-light";}
} ?>
<?php endwhile; ?>
</div>
</div>
Your last if-statment could be:
<?php if(($rowCount % 3) == 0) { ?>
<?php if($count > 6) { echo "-->"; ?>
</div><!-- End lazy load div -->
<?php } ?>
</div><!-- End product centering -->
</div><!-- End row -->
<?php if($rowClass == "internal-product-light"){ $rowClass = "internal-product-dark";}else{$rowClass = "internal-product-light";}
} ?>
And then, after the while-block:
<?php if(($rowCount % 3) <> 0) { ?>
<?php if($count > 6) { echo "-->"; ?>
</div><!-- End lazy load div -->
<?php } ?>
</div><!-- End product centering -->
</div><!-- End row -->
<?php if($rowClass == "internal-product-light"){ $rowClass = "internal-product-dark";}else{$rowClass = "internal-product-light";}
} ?>
The x % y returns the remainder of x/y.
So the following code is actually a much simpler solution than I thought it would be - I will post the code then break it down.
<?php
$count = 0;
$rowCount = 0;
$rowClass = "internal-product-light";
$rowInfo = get_sub_field('product_listing_repeater');
$fieldCount = count($rowInfo);
// check if the repeater field has rows of data
if( have_rows('product_listing_repeater') ): ?>
<div class="internal-container">
<div class="full-product-line-contain">
<?php // loop through the rows of data
while ( have_rows('product_listing_repeater') ) : the_row(); $count++; $rowCount++; ?>
<?php
if($rowCount == 1) { ?>
<div class="<?php echo $rowClass; ?>">
<div class="product-centering">
<?php if($count > 6) { ?>
<div class="js-lazyload">
<?php echo "<!--"; }
} ?>
<div class="internal-section product-line-item product-alignment clearfix">
<div class="product-contain">
<?php if(get_sub_field('has_link')): ?>
<a href="<?php the_sub_field('link_url')?>" class="product-link">
<?php
if(get_sub_field('has_image')):
$singleImage = get_sub_field('block_image');
?>
<img class="product-line-image" src="<?php echo $singleImage ?>" />
<?php endif; ?>
</a>
<?php endif; ?>
<div class="internal-content-contain-right no-float">
<?php if(get_sub_field('has_link')): ?>
<a href="<?php the_sub_field('link_url')?>" class="product-link-title">
<h2><?php the_sub_field('block_headline'); ?></h2>
</a>
<?php endif; ?>
<?php if(get_sub_field('has_link')): ?>
<?php the_sub_field('link_text')?>
<?php endif; ?>
</div>
</div>
</div>
<?php if($rowCount == 3 || $count == $fieldCount) { ?>
<?php if($count > 6 || $count == $fieldCount) { echo "-->"; ?>
</div><!-- End lazy load div -->
<?php } ?>
</div><!-- End product centering -->
</div><!-- End row -->
<?php $rowCount = 0;
if($rowClass == "internal-product-light"){ $rowClass = "internal-product-dark";}else{$rowClass = "internal-product-light";}
} ?>
<?php endwhile; ?>
</div>
</div>
As you can see, I added the variable $fieldCount = count($rowInfo) which counts the ACF repeater field. Then when I was originally checking for 3 products, I added an OR statement - <?php if($rowCount == 3 || $count == $fieldCount) { ?> and to the lazyload check - <?php if($count > 6 || $count == $fieldCount) { echo "-->"; ?>
This makes sure that if it is 3, it closes the div and if it is the end of the array (figured out through count), it closes the div.
Please post any questions for clarification.

Insert static blocks within a PHP loop

I'm trying to insert 2 static div's inside a PHP loop, specifically one at the very beginning of the loop and one at the very end.
These 2 div's must appear within their corresponding .row parent which currently wraps around every 3 DIV's. How can I do this?
EDIT
Here's an image to describe what I need, the pink blocks are the manually inserted div's that will have different content to the blue divs. Those blue divs are just WP posts:
Here's my PHP, currently this creates 4 columns within the first and last rows where it should just be 3 columns:
<?php static $c=1;
$subs = new WP_Query( array( 'post_parent' => 14, 'post_type' => 'page' ));
if( $subs->have_posts() ) : while( $subs->have_posts() ) : $subs->the_post(); ?>
<?php if (($c % 3) === 1) {
// This creates part of the wrapper .row div
echo "<div class='row'>";
} ?>
<?php
if ($c == 1) {?>
<div class="col_4 card bar">
first card that is manually inserted with different content
</div>
<?php } ?>
<a href="<?php the_permalink(); ?>" class="col_4 card bar no-pad <?php if($c % 3 == 0) { echo 'last'; } ?>">
<?php if ( has_post_thumbnail() ) {?>
<div class="feature-image c-1">
<?php the_post_thumbnail('medium'); ?>
</div>
<?php } ?>
<div class="excerpt-wrap">
This is a post from within Wordpress
</div>
</a>
<?php if ($c == 6) {?>
<div class="col_4 card bar">
Last card that is manually inserted with different content
</div>
<?php } ?>
<?php if (($c % 4) === 3) {
echo "</div>";
}?>
<?php $c++; endwhile; endif; wp_reset_postdata(); ?>
EDIT
This is the HTML structure I'd like to achieve:
<!-- very first row -->
<div class="row">
<!-- This is a static block followed by the very first two worpdress posts-->
<div class="static-block"></div>
</div>
<!-- I could have 3 or 30 wordpress posts repeating this format -->
<div class="row">
</div>
<!-- very last row -->
<div class="row">
<!-- These are the very two worpdress posts followed by a static block -->
<div class="static-block"></div>
</div>
<?php
$c = 1;
$subs = new WP_Query(array('post_parent' => 14, 'post_type' => 'page'));
if ($subs->have_posts()) :
?>
<div class='row'>
<?php
while ($subs->have_posts()) : $subs->the_post();
if (($c % 3) == 0 || $c == 3):
?>
</div><div class='row'>
<?php
endif;
?>
<?php
if ($c == 1):
?>
<div class="col_4 card bar">
first card that is manually inserted with different content
</div>
<?php endif; ?>
<a href="<?php the_permalink(); ?>" class="col_4 card bar no-pad <?php if ($c % 3 == 0) { echo 'last'; } ?>">
<?php if (has_post_thumbnail()) { ?>
<div class="feature-image c-1">
<?php the_post_thumbnail('medium'); ?>
</div>
<?php } ?>
<div class="excerpt-wrap">
This is a post from within Wordpress
</div>
</a>
<?php if ($c == 7) { ?>
<div class="col_4 card bar">
Last card that is manually inserted with different content
</div>
<?php } ?>
<?php
$c++;
endwhile;
?>
</div>
<?php
endif;
wp_reset_postdata();
?>
if have more then 7 page and u want to static block add on last just
change 7 to post count value ( $c == $sub->post_count)
EDIT: sorry, it seems that I saw your post before you uploaded the pictures of the wireframe.
It's not so clear to me the goal of your code. But, what I understand is you need to generate an structure like this:
<div class='row'>
<div class='static'>
</div>
<div class='static'>
</div>
#here the loop will create
<div></div>
<div></div>
<div></div>
<div class='static'>
</div>
<div class='static'>
</div>
</div>
and this will be duplicated for as many i in your while you have.
if that is what you need, then I think what you need to do is count 1,2,3 with your $c variable. Everytime you are in $c = 1 print the first 2 static divs, and when you are in $c = 3 print the final 2 static divs. Reset $c to 1 when you reach $c = 3 and include a conditional asking if its the last item and its $c != 3 so you print out the last 2 static divs.

Place DIV's in a containing DIV based on a numeric value

Ive got the follow PHP:
<div class="slide-background">
<div class="slide">
<?php foreach (array_chunk($items->submenu, $linkCount) as $items): ?>
<?php if (12 / $cols == 1):?>
<div class="col-md-12">
<?php else: ?>
<div class="col-md-<?php echo 12 / $cols; ?>">
<?php endif; ?>
<ul>
<?php foreach($items as $submenu): ?>
<?php echo $submenu; ?>
<?php endforeach; ?>
</ul>
</div>
<?php endforeach; ?>
</div>
<ul class="pager">
<li>prev</li>
<li>next</li>
</ul>
</div>
</div>
basically it calculates how many links to display and how many columns, but i now need to place the links in <div class="slide"></div>, but based on the columns.. so basically i need to say if $cols = 2 place two div's in a div and close.. so its basically how many every $cols it should place so many div's in that div..
Its Confusing for me to even explain.. I think Ive explained it rather well above.. If not place say so and ill try again..
Any Help Greatly Appreciated..
UPDATE:
thanks to Hans ive now have the following:
<?php $linksPerColumn = ceil($linkCount / $cols); $linkCounter = 0;?>
<div class="slide-background">
<div class="slide">
<div class="col-md-<?php echo 12 / $cols ?>">
<ul>
<?php foreach ($items->submenu as $link): ?>
<?php $linkCounter++;?>
<?php if($linkCounter % $linksPerColumn == 0):?>
</ul>
</div>
<div class="col-md-<?php echo 12 / $cols ?>">
<ul>
<?php endif; ?>
<?php echo $link; ?>
<?php endforeach; ?>
</ul>
</div>
</div>
<ul class="pager">
<li>prev</li>
<li>next</li>
</ul>
</div>
</div>
only problem is when there's only one column and i need 2 links and then for it to close the div and the ul and start new ones.. right now it does that except for everyone and not for every two links...
You could use modulus for this one. You should calculate how many items you need per column. And then create a close and open div for example:
<?
$linksPerColumn = 4;
if ($linkCount > 4){
$linksPerColumn = ceil ($linkCount / $amountOfColums);
}
$linkCounter = 0;
?>
<div class="slide-background">
<div class="slide">
<?
foreach ($links as $link)
{
$linkCounter++;
?>
// Do your HTML Here.
<?
if($linkCounter % $linksPerColumn = 0)
{
?>
</div>
<div class="slide">
<?
}
?>
</div>
</div>
// Rest of the HTML here.
I think this should do the trick for you.

PHP: Break loop and then continue?

I'm having a problem with the WordPress posts loop. I'd like to break down the post loop, to add some HTML div tags in the post. For example, I'm trying to add a div .wrap around the posts after first post. As it's to wrap the posts, so it should be only once.
The problem is that the .wrap div is being repeated because of the loop. How can I break the loop, and add the .wrap div only once and then continue the loop?
Here's my code:
while ($wp_query->have_posts()) :
$wp_query->the_post();
if($wp_query->current_post <= 1){ ?>
<div class="x">
.. post 1
</div>
<?php }
if($wp_query->current_post > 1){ ?>
<div class="wrap"> <!-- should be only once -->
<div class="y">
.. post 2
</div>
<div class="y">
.. post 3
</div>
</div><!-- should be only once -->
<?php } ?>
endwhile;
Try this
<?php
while ($wp_query->have_posts()) :
$wp_query->the_post();
if($wp_query->current_post <= 1){ ?>
<div class="x">
.. post 1
</div>
<div class="wrap"> <!-- should be only once -->
<?php
$is_wrapped = 1;
}
if($wp_query->current_post > 1){ ?>
<div class="y">
.. post 2, then post 3, ...
</div>
<?php }
endwhile;?>
<?php if (!empty($is_wrapped)){ ?>
</div><!-- should be only once -->
<?php } ?>
You can just use an iterator index, like this:
$i = 0;
while (...) {
if ($i == 1) {
// actions you need to do only once
}
...
$i++
}
<div class="x">
while ($wp_query->have_posts()) :
$wp_query->the_post();
<--print post-->
if($wp_query->current_post <= 1){
</div><div class="y">
}
endwhile;
</div>
You will get an empty <div class="x" /> if there's no post and an empty <div class="y" /> if there's only one post. But may be that's feasible in your case...
edit: example
<?php
$wp_query = new WPDummy;
echo '<div class="x">';
while ($wp_query->have_posts()) :
$wp_query->the_post();
$wp_query->the_content();
if($wp_query->current_post <= 1){
echo '</div>', "\n",'<div class="y">';
}
endwhile;
echo '</div>';
// boilerplate
class WPDummy {
public $current = null;
public $current_post = 0;
public function __construct() {
$this->posts = array( array('content'=>'A'),array('content'=>'B'),array('content'=>'C'),array('content'=>'D') );
}
public function have_posts() {
return false!=current($this->posts);
}
public function the_post() {
$this->current_post+=1;
$this->current = current($this->posts);
next($this->posts);
}
public function the_content() {
echo '<span class="content">', $this->current['content'], '</span>';
}
}
prints
<div class="x"><span class="content">A</span></div>
<div class="y"><span class="content">B</span><span class="content">C</span><span class="content">D</span></div>

Categories