Wrapping every 3 elements in a loop leaves an empty wrapper - php

I am wrapping every 3 elements in my loop in a wrapper div like this:
$query = array(
'post_type' => 'post',
);
$i = 1;
$posts = new WP_Query( $query );
$out = '<div class="wrapper">';
if ($posts->have_posts()){
while ($posts->have_posts()){
$posts->the_post();
$out.= '<div class="content">
//content here
</div>';
if($i % 3 == 0) {
$out .= '</div><div class="wrapper">';
}
$i++;
}
}
$out .= '</div>';
wp_reset_postdata();
return '<section>'.$out.'</section>';
Which creates a good wrapping html minus one little thing that's bothering me:
<section>
<div class="wrapper">
<div class="content"></div>
</div>
<div class="wrapper">
<div class="content"></div>
</div>
<div class="wrapper"></div>
</section>
If I have exactly 6 posts (or any multiple of 3, and modulo is doing this like it should) I'll get an extra empty wrapper. Which is really not needed.
So what conditional should I include in my query to ensure that I don't get empty wrappers?

Add the wrapper inside:
$query = array(
'post_type' => 'post',
);
$i = 1;
$posts = new WP_Query( $query );
$out = '';
$endingNeeded = false;
if ($posts->have_posts()){
while ($posts->have_posts()){
if($i % 3 == 1) {
$out .= '<div class="wrapper">';
$endingNeeded = true;
}
$posts->the_post();
$out.= '<div class="content">
//content here
</div>';
if($i % 3 == 0) {
$out .= '</div>';
$endingNeeded = false;
}
$i++;
}
}
if($endingNeeded) {
$out .= '</div>';
}
wp_reset_postdata();
return '<section>'.$out.'</section>';

Related

Wordpress - Split custom posts into rows and columns

I have a layout where we want to place the custom posts types on alternating rows and 2 & 3 columns.
so basically:
<div class="wrapper">
<div class="row">
<div>post 1</div>
<div>post 2</div>
</div>
<div class="row">
<div>post 3</div>
<div>post 4</div>
<div>post 5</div>
</div>
<!-- then 2 new row with 2 columns followed by 3 columns and so on -->
</div>
Any suggestions?
$args = array(
'posts_per_page' => -1,
'post_type' => 'post',
);
$the_query = new WP_Query($args);
if (!empty($the_query->posts)) {
$count_post_row = 0;
$rowcount = 1;
echo '<div class="wrapper">'; // start wrapper
foreach ($the_query->posts as $post) {
$count_post_row++;
if ($count_post_row == 1) {
echo '<div class="row">'; // start row
}
echo '<div>' . $post->post_title . '</div>';
if ($rowcount == 1 && $count_post_row == 2) {
$count_post_row = 0;
$rowcount = 2;
echo '</div>'; // end row if its first section and 2 post add
}
if ($rowcount == 2 && $count_post_row == 3) {
$rowcount = 1;
$count_post_row = 0;
echo '</div>'; // end row if its second section and 3 post add
}
}
echo '</div>'; // start wrapper
}
This is the code you got your results and its continue as your requirements you can check the screenshot below.. If need any more help drop the comment or message will help..

Merging and ordering XML feeds with PHP - Very slow to load

Within wordpress and using ACF Pro, I'm merging multiple Songkick XML feeds with PHP, attaching an artist name to them (annoyingly each feed doesn't include the artist name), and ordering them by the event date.
I've managed to put this all together (with help from different questions on here) using separate steps, but the page is loading very slowly, so I wondered if there was a way of streamlining or merging some of the steps?
With the code below I am:
Fetching multiple XML feeds (sing an ACF fields from other pages on the site)
Attaching an artist name to each feed
Merging the feeds (whilst removing some of the data to try and speed
up the processing time)
Outputting the information into a table while ordering by date
My code below:
<?php
$args = array(
'post_type' => 'page',
'posts_per_page' => -1,
'post_parent' => 'artists'
);
$parent = new WP_Query( $args );
if ( $parent->have_posts() ) : $artistFeedCount = 0; while ( $parent->have_posts() ) : $parent->the_post(); if( get_page_template_slug() == 'template-artist.php' && 'publish' === get_post_status() ) {
$singleArtistName = get_the_title();
$singleArtistSongkickRSS = 'https://api.songkick.com/api/3.0/artists/' . get_field('artist_songkick_id') . '/calendar.xml?apikey=XXXXXXXXXXXXXXXX';
$SongkickEvents[]=$singleArtistName;
$SongkickEvents[$singleArtistSongkickRSS] = $SongkickEvents[$artistFeedCount];
unset($SongkickEvents[$artistFeedCount]);
$artistFeedCount++;
?>
<?php }; endwhile; ?>
<?php endif; wp_reset_postdata(); ?>
<?php
$eventsDom = new DOMDocument();
$eventsDom->appendChild($eventsDom->createElement('events'));
foreach ($SongkickEvents as $artist_dates => $artist_name ) {
$eventsAddDom = new DOMDocument();
$eventsAddDom->load($artist_dates);
$events = $eventsAddDom->getElementsByTagName('event');
if ($eventsAddDom->documentElement) {
foreach ($events as $event) {
$eventsDom->documentElement->appendChild(
$eventsDom->importNode($event, TRUE)
);
$artistName = $eventsDom->createElement('mainartist', $artist_name);
foreach($eventsDom->getElementsByTagName('event') as $singleEvent) {
$singleEvent->appendChild($artistName);
}
foreach($eventsDom->getElementsByTagName('performance') as $singlePerformance) {
$singlePerformance->parentNode->removeChild($singlePerformance);
}
}
}
}
$newXML = $eventsDom->saveXml();
$LiveDates = simplexml_load_string($newXML);
$eventsArr=array();
foreach($LiveDates->event as $eventsArrSingle)
{
$eventsArr[]=$eventsArrSingle;
}
usort($eventsArr,function($dstart,$dend){
return strtotime($dstart->start['date'])-strtotime($dend->start['date']);
});
foreach($eventsArr as $eventsArrSingle) { ?>
<div class="event-row <?php $eventStatus = $eventsArrSingle['status']; if($eventStatus == 'cancelled' || $eventStatus == 'postponed'): echo 'cancelled'; endif; ?>">
<div class="event-block event-date">
<span><?php $eventDate=$eventsArrSingle->start['date']; echo date("d", strtotime($eventDate)); ?></span>
<?php echo date("M", strtotime($eventDate)); ?>
</div>
<div class="event-block event-info">
<span><?php echo $eventsArrSingle->mainartist; ?></span>
<?php if($eventsArrSingle->venue['displayName'] != 'Unknown venue'): echo $eventsArrSingle->venue['displayName'] . ', '; endif; ?><?php echo $eventsArrSingle->venue->metroArea['displayName']; ?>
</div>
<div class="event-block event-button">
<span><?php if($eventStatus == 'cancelled'): echo 'Cancelled'; elseif($eventStatus == 'postponed'): echo 'Postponed'; else: echo 'Tickets'; endif; ?></span> <i class="fas fa-arrow-right"></i>
</div>
</div>
<?php };?>
Any help would be greatly appreciated, I'm sure there's a way of merging everything in fewer steps!
For anyone coming across the same issue, this is the solution I used. Using the Transient API to store the feed for 3 hours at a time.
<?php
function eventsFunction() {
// Do we have this information in our transients already?
$eventTransient = get_transient( 'eventsTransientData' );
// Yep! Just return it and we're done.
if( ! empty( $eventTransient ) ) {
echo $eventTransient;
} else {
$single_artist_ids = array(
'post_type' => 'page',
'posts_per_page' => -1,
'post_parent' => 'artists'
);
$parent = new WP_Query( $single_artist_ids );
if ( $parent->have_posts() ) : $artistFeedCount = 0; while ( $parent->have_posts() ) : $parent->the_post(); if( get_page_template_slug() == 'template-artist.php' && 'publish' === get_post_status() ) {
$singleArtistName = get_the_title();
$singleArtistSongkickRSS = 'https://api.songkick.com/api/3.0/artists/' . get_field('artist_songkick_id') . '/calendar.xml?apikey= XXXXXXXXXXXXXXXX';
$SongkickEvents[]=$singleArtistName;
$SongkickEvents[$singleArtistSongkickRSS] = $SongkickEvents[$artistFeedCount];
unset($SongkickEvents[$artistFeedCount]);
$artistFeedCount++;
?>
<?php }; endwhile; ?>
<?php endif; wp_reset_postdata(); ?>
<?php
$eventsDom = new DOMDocument();
$eventsDom->appendChild($eventsDom->createElement('events'));
foreach ($SongkickEvents as $artist_dates => $artist_name ) {
$eventsAddDom = new DOMDocument();
$eventsAddDom->load($artist_dates);
$events = $eventsAddDom->getElementsByTagName('event');
if ($eventsAddDom->documentElement) {
foreach ($events as $event) {
$eventsDom->documentElement->appendChild(
$eventsDom->importNode($event, TRUE)
);
$artistName = $eventsDom->createElement('mainartist', $artist_name);
foreach($eventsDom->getElementsByTagName('event') as $singleEvent) {
$singleEvent->appendChild($artistName);
}
foreach($eventsDom->getElementsByTagName('performance') as $singlePerformance) {
$singlePerformance->parentNode->removeChild($singlePerformance);
}
}
}
}
$eventsXML = $eventsDom->saveXml();
$LiveDates = simplexml_load_string($eventsXML);
$eventsArr=array();
foreach($LiveDates->event as $eventsArrSingle)
{
$eventsArr[]=$eventsArrSingle;
}
usort($eventsArr,function($dstart,$dend){
return strtotime($dstart->start['date'])-strtotime($dend->start['date']);
});
$eventsStored = '';
foreach($eventsArr as $eventsArrSingle) {
$eventsStored .= '<div class="event-row ';
$eventStatus = $eventsArrSingle['status']; if($eventStatus == 'cancelled' || $eventStatus == 'postponed'): $eventsStored .= 'cancelled'; endif;
$eventsStored .= '">
<div class="event-block event-date">
<span>';
$eventDate=$eventsArrSingle->start['date']; $eventsStored .= date("d", strtotime($eventDate));
$eventsStored .= '</span>';
$eventsStored .= date("M", strtotime($eventDate));
$eventsStored .= '</div>
<div class="event-block event-info">
<span>';
$eventsStored .= $eventsArrSingle->mainartist;
$eventsStored .= '</span>';
if($eventsArrSingle->venue['displayName'] != 'Unknown venue'): $eventsStored .= $eventsArrSingle->venue['displayName'] . ', '; endif;
$eventsStored .= $eventsArrSingle->venue->metroArea['displayName'];
$eventsStored .= '</div>
<div class="event-block event-button">
<a href="' . $eventsArrSingle['uri'] . '" target="_blank"><span>';
if($eventStatus == 'cancelled'): $eventsStored .= 'Cancelled'; elseif($eventStatus == 'postponed'): $eventsStored .= 'Postponed'; else: $eventsStored .= 'Tickets'; endif;
$eventsStored .= '</span> <i class="fas fa-arrow-right"></i></a>
</div>
</div>';
};
set_transient( 'eventsTransientData', $eventsStored, 3*HOUR_IN_SECONDS );
echo $eventsStored;
}
}
eventsFunction();
?>

How to add odd and even class in group?

I want to add odd and even class in pairing. So how can i do it with php.
<div class="root">
<div class="odd">
</div>
<div class="odd">
</div>
<div class="even">
</div>
<div class="even">
</div>
</div>
I want to create structure in wordpress post loop.
$args = array(
'post_type' => 'post',
'posts_per_page' => $postsPerPage,
'cat' => 1
);
$html = '';
// The Query
$query = new WP_Query( $args );
if( $query->have_posts()){
while ( $query->have_posts() ) {
}
}
So how can i do it. Please suggest me some ideas.
Use counter to check how many row you have printed and reset it when you want to start over:
<?php
if ($query->have_posts()) {
$count = 0;
while ($query->have_posts()) {
if($count < 2){
// add <div class="odd"> block here
}else{
// add <div class="even"> block here
}
$count++;
if($count == 4){
$count = 0;
}
}
}
?>
Use This
$class = 'even';
echo '<div class="root">';
while ($query->have_posts()) {
$class = $class != 'even' ? 'even' : 'odd';
echo "<div class='{$class}'></div>";
echo "<div class='{$class}'></div>";
}
echo "</div>";

How do I get multiple images from a single string

I've looked around and haven't found a answer that did it for me. I don't want all the images from an HTML page. I just want all the images from a single string.
On a page, I'm using two different strings. I want all the images that are within the second image. I want to loop them into a carousel.
I've looked around a bit and this is what I got:
function GetImgString($plaatje){
preg_match_all('/<img[^>]+>/i',$plaatje, $result);
$house = $result[0];
$i = 1;
$output = '<div class="carousel-inner">';
foreach ( $house as $houses ) {
if ($i == 1) {
$output.= '<div class="item active">';
}else{
$output.= '<div class="item">';
}
$output.=
$house.'
<div class="container">
<div class="carousel-caption">
</div>
</div>
</div>
';
$i++;
}
$output .= '</div>';
return $house;}
This is the output:
Array
(
[0] => &ltimg src="images/Huizen/huis-3.jpg" alt="" />
[1] => &ltimg src="images/Huizen/huis-4.jpg" alt="" />
)
How do I solve this?
I assume, when you do the regexp, in your results, there are the 2 images.
You are start to building your output into a variable, calles $output, but you return with $house, what contain the 2 result from preg_match.
So you can try with this:
function GetImgString($plaatje) {
preg_match_all('/<img[^>]+>/i', $plaatje, $result);
$houses = $result[0];
$houses = str_ireplace('<', '&lt', $house);
$houses = str_ireplace('>', '&gt', $house);
$i = 1;
$output = '<div class="carousel-inner">';
foreach ($houses as $house) {
$class = ' class="item"';
if ($i === 1) {
$class = ' class="item active"';
}
$output.= '<div '.$class.'>';
$output.= $house . '
<div class="container">
<div class="carousel-caption"></div>
</div>
</div>' . "\n";
$i++;
}
$output .= '</div>';
return $output;
}

PHP While Loop wrapping every 4 results with a li

i am trying to wrap each 4 results inside a LI and repeat for every 4 items like
<li>
<div>item 1</div>
<div>item 2</div>
<div>item 3</div>
<div>item 4</div>
</li>
PHP so far.... the loop ive attempted is of course not working :)
if ( $query->have_posts() ) {
$opnews .= '<ul class="newsitems orbit-slides-container">';
$count = 0;
while ( $query->have_posts() ) : $query->the_post();
$post_id = get_the_ID();
$opnews_item_data = get_post_meta( $post_id, 'opnews_item', true );
if ($i%4 == 1) {
$opnews .= '<li>';
}
$opnews .= '<div class="columns large-3 small-12 medium-3">';
$opnews .= '<div class="panel green opacity-change">';
$opnews .= '<h1>' . get_the_title() . '</h1>';
$opnews .= get_the_content_with_formatting();
$opnews .= '</div>';
$opnews .= '</div>';
if ($count%4 == 0) {
$opnews .= '</li>';
}
endwhile;
$opnews .= '</ul>';
wp_reset_postdata();
}
You are using $i and $count, so pick only one.
Then you have to increment it between your <li> to get it working.
And finally, you should check, once you finished the loop, that the last <li> has been echoed or you will get some trouble (a missing </li>)
$array = range(1, 9);
$i = 0;
foreach ($array as $val) {
if ($i%4 == 0) echo '<li>';
$i++;
echo $val;
if ($i%4 == 0) echo '</li>';
}
if ($i%4 != 0) echo '</li>';
Output :
<li>
1 2 3 4
</li>
<li>
5 6 7 8
</li>
<li>
9
</li>
The modulus operator (%) divides the number and returns the remainder. So, your line if ($i%4 == 1) probably isn't what you're after, as if it's every 4th row, you'll want it with no remainder.
The $count%4 == 0 line also doesn't make much sense to me, as you're not incrementing the number. You're also not incrementing $i.
Try the following:
if ( $query->have_posts() ) {
$opnews .= '<ul class="newsitems orbit-slides-container">';
$i = 0;
while ( $query->have_posts() ) : $query->the_post();
$post_id = get_the_ID();
$opnews_item_data = get_post_meta( $post_id, 'opnews_item', true );
if ($i%4 == 0) {
if ($i != 0){
$opnews .= '</li>';
}
$opnews .= '<li>';
}
$opnews .= '<div class="columns large-3 small-12 medium-3">';
$opnews .= '<div class="panel green opacity-change">';
$opnews .= '<h1>' . get_the_title() . '</h1>';
$opnews .= get_the_content_with_formatting();
$opnews .= '</div>';
$opnews .= '</div>';
$i++;
endwhile;
$opnews .= '</li>';
$opnews .= '</ul>';
wp_reset_postdata();
}
It's not working because you never change count. Count is always 0, so $count % 4 == 0 is always true. Also, unless it's somewhere else you haven't defined i.
Use only count (or only i).
if ($count % 4 == 0) {
$opnews .= '<li>';
}
DO STUFF HERE
$count += 1
if ($count % 4 == 0) {
$opnews .= '</li>';
}
It looks like you're mixing both $i and $count. One of them you're using the modulous operator and comparing if the remainder after division is 1, and the other you're comparing if the remainder is 0. Neither of them seems to be incrementing (and $i doesn't look to be defined from the snippet you've provided).
Choose one, $count, and compare it with 0 using the modulous and be sure to increment it within the loop:
if ($count % 4 == 0) {
$opnews .= '<li>';
}
// ...
$count++;
if ($count % 4 == 0) {
$opnews .= '</li>';
}

Categories