How to apply markup to every third item in WordPress? - php

I am using the following markup to display different image crop sizes, depending on the item number:
<?php
$images = get_field('portfolio-gallery');
$size = 'full';
if( $images ):
?>
<ul class="cf">
<?php foreach( $images as $index => $image ): ?>
<li>
<?php if ( $index == 0 ) { ?>
<img src="<?php echo $image['sizes']['gallery-1']; ?>" alt="<?php echo $image['alt']; ?>" />
<?php } elseif ( $index == 1 ) { ?>
<img src="<?php echo $image['sizes']['gallery-2']; ?>" alt="<?php echo $image['alt']; ?>" />
</li>
<?php } endforeach; ?>
</ul>
<?php endif; ?>
However I want to know if it's possible to adjust this markup so that rather than specifying each number individually, I can tell it to apply the specific markup to every third item, for example.

To specify that the markup should apply to every third item you could use something like:
<?php if ( $index % 3 == 0 ) { ?>
<img src="<?php echo $image['sizes']['gallery-1']; ?>" alt="<?php echo $image['alt']; ?>" />
This would apply the given markup to the 1st, 4th, 7th etc. image, assuming that $index starts at 0. If you wanted to apply it to the 3rd, 6th, 9th, you would use ($index - 2) % 3 == 0 instead.

Related

Php foreach loop, add to different div depending on if/else

My current code:
<?php if($_images){?>
<?php $i=0; foreach($_images as $_image){ $i++; ?>
<?php if($i > 2) { ?>
<div class = "largePic">
<img src="<?php echo $this->helper('catalog/image')->init($_product, 'thumbnail', $_image->getFile())->resize(600,900); ?>" alt="<?php echo $this->htmlEscape($_image->getLabel());?>" title="<?php $this->htmlEscape($_image->getLabel());?>" />
</div>
<?php } else { ?>
<div class = "smallPic">
<img src="<?php echo $this->helper('catalog/image')->init($_product, 'thumbnail', $_image->getFile())->resize(450,675); ?>" alt="<?php echo $this->htmlEscape($_image->getLabel());?>" title="<?php $this->htmlEscape($_image->getLabel());?>" />
</div>
<?php } ?>
<?php } ?>
<?php } ?>
So this is obviously wrong since every time an image is echo'ed it's assigned to a different div (same name but different). Is it possible to assign echoes to certain div depending on the count?
For example, first two images will be assigned to the smallPic div, then the rest will be in the largePic div.
Process the images first (storing the HTML for each image in either an array or string) and then create the div elements- see example below. This will reduce the number of opening/closing tags immensely.
Also note that if the keys of the array are numeric then the following syntax can be used instead of creating an extra variable (i.e. $i) just to track the index (so as to avoid extra bookkeeping like incrementing the variable - one of the major benefits of foreach compared to a for statement).
foreach (array_expression as $key => $value)
statement 1
<?php
$largePic = '';
$smallPic = '';
if($_images){
foreach($_images as $i => $_image){
if($i > 2) {
$largePic .= '<img src="'.$this->helper('catalog/image')->init($_product, 'thumbnail', $_image->getFile())->resize(600,900).'" alt="'. $this->htmlEscape($_image->getLabel()). '" title="'. $this->htmlEscape($_image->getLabel()).'" />';
} else {
$smallPic .= '<img src="'. $this->helper('catalog/image')->init($_product, 'thumbnail', $_image->getFile())->resize(450,675). '" alt="'. $this->htmlEscape($_image->getLabel()). '" title="'. $this->htmlEscape($_image->getLabel()). '" />';
}
}
} ?>
<div class = "largePic"><?php echo $largePic; ?></div>
<div class = "smallPic"><?php echo $smallPic; ?></div>
What you want is to first devide your array into two arrays and then foreach through both of them.
<?php
$largeImages = array();
$smallImages = array();
foreach ($_images as $k => $v) {
if ($k > 2) {
$largeImages[] = $v;
} else {
$smallImages[] = $v
}
}
?>
<div class = "largePic">
<?php foreach ($largeImages as $_image) { ?>
<img src="<?php echo $this->helper('catalog/image')->init($_product, 'thumbnail', $_image->getFile())->resize(600,900); ?>" alt="<?php echo $this->htmlEscape($_image->getLabel());?>" title="<?php $this->htmlEscape($_image->getLabel());?>" />
<?php } ?>
</div>
<div class = "smallPic">
<?php foreach ($smallImages as $_image) { ?>
<img src="<?php echo $this->helper('catalog/image')->init($_product, 'thumbnail', $_image->getFile())->resize(450,675); ?>" alt="<?php echo $this->htmlEscape($_image->getLabel());?>" title="<?php $this->htmlEscape($_image->getLabel());?>" />
<?php } ?>
</div>
I'm not in PHP but I'm quite sure for start you can loose those extensive open/close tags (<?php ?>) and replace it with only one at the start and the end. This is hardly readable.
Then, like in many server side scripts, what you need is some kind of buffer containing HTML which you will output at the end of loop. Because what you're doing now is outputting from inside the loop, this sending multiple DIVs to client.
Create largePic nad smallPic variables contianing DIVs HTML, and append HTML to it inside loop (instead outputing it to client like you do now). Then, after loop is finished, output those two variables to client.

How can I getMediaGalleryImages within a sort order range in Magento?

I am new to Magento.
How can I getMediaGalleryImages within a sort order range in Magento? I am new to magento and would like to get all images for a product within a sort oorder range of say 10-20.
This is what I have so far:
<?php $_images = Mage::getModel('catalog/product')->load($_product->getId())- >getMediaGalleryImages();?>();?><?php if($_images){?><?php $i=0; foreach($_images as $_image) if ($i++ < 8) { $i++;?>
Any help is welcome!
Thanks for the answers but, I'm not quite getting it I'm afraid, I want to display thumbs under my products on the product list page. I'm sure the code you have given is correct but I am not implementing it correctly. Here's the full code for that I have at the moment:
<?php $_images = Mage::getModel('catalog/product')->load($_product->getId())- >getMediaGalleryImages();?>
<?php if($_images){?>
<?php $i=0; foreach($_images as $_image){ $i++; if($i>=10 && $i<=20);?>
<a href="#">
<img src="<?php echo $helpImg->getImg($_product, $bigImageWidth, $bigImageHeight, 'image', $_image->getFile()); ?>" class="cloud-zoom-gallery lightbox-group"
title="<?php echo $this->escapeHtml($_image->getLabel()); ?>" width="25" height="25" alt="<? =$this->htmlEscape($_image->getLabel());?>" title="<?=$this->htmlEscape($_image->getLabel());?>" />
you need to change code
$_images = Mage::getModel('catalog/product')->load($_product->getId())->getMediaGalleryImages();
$i=1;
foreach($_images as $_image){
if($i > 10 && $i < 20){
echo $_image['url'];
}
$i++;
}
You can do it by doing following code.
<?php $_images = Mage::getModel('catalog/product')->load($_product->getId())->getMediaGalleryImages(); ?>
<?php if($_images){?>
<?php $i=0; foreach($_images as $_image){ $i++; if($i>=10 && $i<=20): ?>
<img src="<?php echo $this->helper('catalog/image')->init($_product, 'thumbnail', $_image->getFile())->resize(108,90); ?>" alt="<?php echo $this->htmlEscape($_image->getLabel());?>" title="<?php $this->htmlEscape($_image->getLabel());?>" /><?php endif; } ?>
<?php } ?>
Change the range whatever you want.
This is example for product gallery images order from 10 to 20.

Two items per foreach loop

Apologies if this has already been asked (I cannot find an answer) but I am using PHP and I am building a slider, but would like two images per slide, not one. So, in theory the foreach() needs to include two per each.
An example of the setup is as follows:
<?php foreach ($page->images as $image) : ?>
<img src="<?php echo $image->url; ?>"/>
<?php endforeach; ?>
I was thinking I could do something like a count...
<?php $index = 0; foreach ($page->images as $image) : ?>
<img src="<?php echo $image->url; ?>"/>
<?php $index++; ?>
<?php if ( $index % 2 == 0 && $index !=count($page->images) ) : ?>
<li></li>
<?php endif; ?>
<?php endforeach; ?>
But I got a little confused as this would insert something every 2... not include two of whatever the foreach loop is fetching at once.
Hope this makes sense and thanks in advance
Why so complicated? Use a simple for loop instead:
<?php for ($i=0; $i<count($page->images)-1; $i+=2) { ?>
<img src="<?php echo $page->images[$i]->url; ?>"/>
<img src="<?php echo $page->images[$i+1]->url; ?>"/>
<?php } ?>
Or even more elegant, a do/while loop:
<?php $i=0; do { ?>
<img src="<?php echo $page->images[$i++]->url; ?>"/>
<img src="<?php echo $page->images[$i++]->url; ?>"/>
<?php } while ($i<count($page->images)) ?>
Compared to using a foreach loop these approaches have another advantage: you do not create copies of all objects. This can make a huge difference if those objects are non-trivial.
Okay, I managed to work this out... hopefully it will help.
<div class="each-slide">
<?php $index = 0; foreach ($page->images as $image) : ?>
<img src="<?php echo $image->url; ?>"/>
<?php $index++; ?>
<?php if ( $index % 2 == 0 && $index !=count($page->images) ) : ?>
</div><div class="each-slide">
<?php endif; ?>
<?php endforeach; ?>
</div>

Offset PHP array results

I am looking to offset a group of PHP array results to create multiple rows of data.
For example, the first row will contain the first four array results, with the second row displaying results 5-8 and the third row containing results 9-12.
Currently, I am printing out all 12 in one list, however I'd like a bit more display control (i.e. ordering the results into columns which I can style independent of each), hence why I'd like to offset the results.
My current PHP is below:
<?php
if (empty($tmdb_cast['cast'])) {
} else {?>
<section class="cast">
<p class="title">Cast</p>
<ul class="section_body"><?php
foreach($tmdb_cast['cast'] as $key => $castMember){
if ($key < 12) {?>
<li class="actor_instance clearfix"><?php
if ($castMember['profile_path'] != '') {?>
<img src="http://cf2.imgobject.com/t/p/w45<?php echo $castMember['profile_path']; ?>" class="actor_image pull-left" alt="<?php echo $castMember['name']; ?>" title="<?php echo $castMember['name']; ?>" /><?php
} else {?>
<img src="assets/images/castpic_unavailable.png" class="actor_image pull-left" alt="No image available" title="No image available" /><?php
}?>
<p class="actor"><?php echo $castMember['character']; ?> - <?php echo $castMember['name']; ?></p>
</li><?php
}
}?>
<div class="morecast pull-right">[...view all cast]</div>
</ul>
</section><?php
}?>
P.S. Apologies for how I've formatted the code in the above block - I'm still not 100% sure how to make it look "nice" on StackOverflow.
Use array_chunk to break a single dimension array into a 2D array. Then you can loop through each chunk, and then each result, to get that "offset" effect between them.
$chunks = array_chunk($tmdb_cast['cast'], 4); // 4 here, is the number you want each group to have
foreach($chunks as $key => $chunk)
{
foreach($chunk as $castMember)
{
//display castMember here
}
// add code between groups of 4 cast members here
}
First: mixing php and html this way is a very bad habbit... one day you will have to maintain your code and that day you will vomit all over your desk because you mixed different languages in one file...
That being said..
and without creating a new array:
foreach($tmdb_cast['cast'] as $key => $castMember)
{
if ($key < 12)
{
// your code goes here
// if key is 3, or 7 the code below will close the listcontainer and open a new one...
if( ($key+1)%4 == 0 AND $key <11)
echo '</ul> <ul class="section_body">';
}
}
Also replace this:
if (empty($tmdb_cast['cast']))
{
}
else {
with this:
if (!empty($tmdb_cast['cast']))
{
I'm not entirely sure what you're looking for but here's how I would format your code. Alternative syntax for 'if' is a little more readable, and the use of for loops instead of a foreach will give you the control over row numbers you say you're looking for.
<?php if( ! empty($tmdb_cast['cast'])): ?>
<section class="cast">
<p class="title">Cast</p>
<ul class="section_body">
<?php
for($i = 0; $i < 12; $i++):
$castMember = $tmdb_cast['cast'][$i];
?>
<li class="actor_instance clearfix">
<?php if($castMember['profile_path'] != ''): ?>
<img src="http://cf2.imgobject.com/t/p/w45<?php echo $castMember['profile_path']; ?>" class="actor_image pull-left" alt="<?php echo $castMember['name']; ?>" title="<?php echo $castMember['name']; ?>" />
<?php else: ?>
<img src="assets/images/castpic_unavailable.png" class="actor_image pull-left" alt="No image available" title="No image available" />
<?php endif; ?>
<p class="actor"><?php echo $castMember['character']; ?> - <?php echo $castMember['name']; ?></p>
</li>
<?php endfor; ?>
<div class="morecast pull-right">[...view all cast]</div>
</ul>
</section>
<?php endif; ?>

PHP + Wordpress : foreach repeat html structure after every nth

I am trying to achieve result with below structure in foreach loop where after every two images it will repeat entire structure.
I have some basic knowledge for something I can use eg. counter++; and than %2 but don't know syntax and how to use it for my code.
<?php
function dt_attached($postid=0, $size='thumbnail', $attributes='', $linksize='full', $count=-1) {
if ($postid<1) $postid = get_the_ID();
if ($images = get_children(array(
'post_parent' => $postid,
'post_type' => 'attachment',
'numberposts' => $count,
'post_mime_type' => 'image',)))
foreach($images as $image) {
$attachment=wp_get_attachment_image_src($image->ID, 'thumbnail');
$small_image = wp_get_attachment_image_src($image->ID, 'midium');
$big_image = wp_get_attachment_image_src($image->ID, 'full');
?>
<div class="mainrow">
<div class="block">
<a href='<?php echo $big_image[0]; ?>' class='cloud-zoom-gallery' title='Thumbnail 1' rel="useZoom: 'zoom1', smallImage: '<?php echo $small_image[0]; ?>' ">
<img src="<?php echo $attachment[0]; ?>" <?php echo $attributes; ?> />
</a>
</div>
<!--[I want to get two images in mainrow]-->
<div class="block">
<a href='<?php echo $big_image[0]; ?>' class='cloud-zoom-gallery' title='Thumbnail 1' rel="useZoom: 'zoom1', smallImage: '<?php echo $small_image[0]; ?>' ">
<img src="<?php echo $attachment[0]; ?>" <?php echo $attributes; ?> />
</a>
</div>
</div>
<?php //the_attachment_link($image->ID, false, true, false); ?>
<?php }
}
?>
So what I want is if there is more than two images it will repeat entire html structure. Thanks a lot for your help
What I gathered from your comments is that you want to display two images per row, and if there's one extra image, to display a placeholder next to it in the final row.
All you need is a count of how many images there are, and whether it's an even or odd number. Then once you know you're at the last image (using an incrementing counter), you add the placeholder:
What your code doesn't do is place two images in one row. For that we need to take the modulo (%) of the counter as well.
<?php
$counter = 0;
$imgCount = count($images);
foreach ($images as $image) {
$attachment = wp_get_attachment_image_src($image->ID, 'thumbnail');
$small_image = wp_get_attachment_image_src($image->ID, 'midium');
$big_image = wp_get_attachment_image_src($image->ID, 'full');
if ($counter % 2 == 0): ?>
<div class="mainrow">
<?php endif; ?>
<div class="block">
<a href='<?php echo $big_image[0]; ?>' class='cloud-zoom-gallery' title='Thumbnail 1' rel="useZoom: 'zoom1', smallImage: '<?php echo $small_image[0]; ?>' ">
<img src="<?php echo $attachment[0]; ?>" <?php echo $attributes; ?> />
</a>
</div>
<?php if ($counter++ % 2 == 1): ?>
</div>
<?php endif; ?>
<?php //the_attachment_link($image->ID, false, true, false); ?>
<?php
}
// Since (if there are an odd number of images) the loop may not close the <div>,
// we have to make sure it does.
if ($counter % 2 == 0) {
?>
<!-- placeholder goes here -->
</div>
<?php
}

Categories