Question

PHP Re-loop a foreach loop to sort images according to size

I have an array of images.

In the array, for each image, I have whether the image is tall or wide.

I need to loop through all of the images, and pair a tall with wide into a div, then move to the next until they are all done.

I have something that sort of works using a foreach loop, but the problem is that some images get skipped … the loop stops when each image has gone through the loop, which is standard behavior for a “foreach” loop, from what I have read…

So now I am wondering if there is a different loop I should use, or should I put my foreach loop inside another loop so that it repeats until the images are used up?

Here is my loop so far, that does what I want, but leaves out several images:



        $num_of_images = count($images);
        $notins = array();
                $order  = 1;
        $i = 0;
                 //start my loop
         foreach ($images as $image) {
            $id = $image->ID;
                         //check if image is in the notins array..skips if it is
                          if (!in_array($id, $notins)){
                          //find out if the image is tall or wide
               $attach = wp_get_attachment_image_src(  $id, 'full');
               $height = $attach['2'];
                $width = $attach['1'];  
                 if ($height < $width) { $size = "wide" ;} else { $size = "tall" ;}
                           //get the link to the sized image
               $preview_array = image_downsize( $image->ID, $size );
               $img_preview = $preview_array[0]; // thumbnail or medium image to use for preview.



                
                 if( $order == 3 ){   //if previous slide was tall, get a wide slide
                    if($size == "wide") { $order = 1; array_push($notins, $id); $i++; ?>
<!-- - - - - - - - - - - Image - - - - - - - - - - - - - -->    
<div class="image <?php echo $size; ?>" style="background: url(<?php echo $img_preview; ?>) no-repeat center !important; background-size: cover !important; max-width: 100%; "> 
    </div>    
    <!-- - - - - - - - - - - end Image  - - - - - - - - - - - - - -->
</li><!--.slide --><?php
  
                                   }
                }  


                    if( $order == 2 ){    //if previous slide was wide, get a tall slide
                    if($size == "tall"  ) {  $order = 1; array_push($notins, $id); $i++;  ?>
<!-- - - - - - - - - - - Image - - - - - - - - - - - - - -->    
    <div class="image <?php echo $size; ?>" style="background: url(<?php echo $img_preview; ?>) no-repeat center !important; background-size: cover !important; max-width: 100%; "> 
    </div>    
    <!-- - - - - - - - - - - end Image  - - - - - - - - - - - - - -->
                        </li><!--.slide --><?php 

                                     }
                 }  

                


                  if( $order == 1) {   //if this is the first slide in the div
                    if( !in_array($id, $notins) ) {   $i++;  array_push($notins, $id);  ?>

<li class="the-slide gallery">
    <!-- - - - - - - - - - - Image - - - - - - - - - - - - - -->    
    <div class="image <?php echo $size; ?>" style="background: url(<?php echo $img_preview; ?>) no-repeat center !important; background-size: cover !important; max-width: 100%; ">  
</div>    
    <!-- - - - - - - - - - - end Image  - - - - - - - - - - - - - --><?php 
               
                                   
                             if( $i == 17 ){ ?> </div><!--.slide --> <?php  } 
                     if($size == "wide"){ $order = 2; } if($size == "tall"){  $order = 3;  }  } }



            }   
        }
    }
Show comments

Submit an answer


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

KFSys
Site Moderator
Site Moderator badge
June 12, 2023
Pinned Answer

Heya all,

The main issue with your approach is that the foreach loop goes through each image only once and there’s no guarantee that the images will come in the sequence tall, wide, tall, wide, and so on.

A better approach is to divide your images into two separate arrays, one for tall images and one for wide images, then pair them together.

Here’s a rough idea of how you could modify your code:

$tallImages = [];
$wideImages = [];

// Divide the images into two arrays based on their dimensions
foreach ($images as $image) {
    $attach = wp_get_attachment_image_src($image->ID, 'full');
    $height = $attach['2'];
    $width = $attach['1'];

    if ($height < $width) {
        $wideImages[] = $image;
    } else {
        $tallImages[] = $image;
    }
}

// Assuming that the number of tall images and wide images is the same,
// pair them together
for ($i = 0; $i < count($tallImages); $i++) {
    $tallImage = $tallImages[$i];
    $wideImage = $wideImages[$i];

    // Your code for outputting the div here, using $tallImage and $wideImage
    // e.g. outputImage($tallImage); outputImage($wideImage);
}

This is a simplified version of the code and you may need to modify it according to your needs. Please note that this code assumes that there are an equal number of tall and wide images. If this isn’t the case, you would need to add some additional logic to handle the situation where there are more images of one type than the other.

The outputImage() function used in this example should be a function where you put your code that generates the image HTML. You pass either a tall or a wide image to this function.

This way, you are certain that each tall image will be paired with a wide image in sequence.

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
June 7, 2016

This question was answered by @sierracircle:

Okay, using @ryanpq idea of putting everything into two arrays has worked. I can reverse the order of using the larger or smaller of the two arrays, depending on if I want images to show up that do not have a partner image.

Here are my loops (tested and works):

if ($images) { 

			$tall = array();
			$wide = array();
			foreach ($images as $image) {
			   $id = $image->ID;                    
			   $attach = wp_get_attachment_image_src(  $id, 'full');
			   $height = $attach['2'];
		 	   $width = $attach['1'];  
			     if ($height < $width) { $size = "wide" ;} else { $size = "tall" ; }
				  if( $size == 'tall') {  array_push($tall, $id); } 
				  if( $size == 'wide') {  array_push($wide, $id); } 

			    } //get everything into two arrays

			//get the larger and smaller of the two arrays
			if(count($tall) > count($wide)){ 
$large = $tall; $small = $wide; $size = "tall"; $sm_size = "wide"; 
}  
				else { $large = $wide; $small = $tall; $size = "wide"; $sm_size = "tall";}  

			//now loop through the smaller array
			 $i = 0;
                        foreach($large as $image) {
				$id = $image;
				$previews = image_downsize( $id, $size );
			        $img = $previews[0];  
				$sm_id = $small[$i];
				$sm_previews = image_downsize( $sm_id, $sm_size );
			        $sm_img = $sm_previews[0];  



													?>
			     
<li class="the-slide gallery">
   <!-- - - - - - - - - - - Image - - - - - - - - - - - - - -->	
	<div class="image <?php echo $size; ?>" style="background: url(<?php echo $img; ?>)
no-repeat center !important; background-size: cover !important; max-width: 100%; ">
</div>	
   <!-- - - - - - - - - - - end Image  - - - - - - - - - - - - - -->
   <!-- - - - - - - - - - - Image - - - - - - - - - - - - - -->	
	<div class="image <?php echo $sm_size; ?>" style="background: url(<?php echo
$sm_img; ?>) no-repeat center !important; background-size: cover !important; max-width: 100%; ">
</div>	
   <!-- - - - - - - - - - - end Image  - - - - - - - - - - - - - -->


					

			<?php $i++;  }

		  
		     

	} //if images

View the original comment

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel