81

I'm having problem with nested loop. I have multiple number of posts, and each post has multiple number of images.

I want to get total of 5 images from all posts. So I am using nested loop to get the images, and want to break the loop when the number reaches to 5. The following code will return the images, but does not seem to break the loop.

foreach($query->posts as $post){
        if ($images = get_children(array(
                    'post_parent' => $post->ID,
                    'post_type' => 'attachment',
                    'post_mime_type' => 'image'))
            ){              
                $i = 0;
                foreach( $images as $image ) {
                    ..
                    //break the loop?
                    if (++$i == 5) break;
                }               
            }
}
Athari
  • 33,702
  • 16
  • 105
  • 146
user1355300
  • 4,867
  • 18
  • 47
  • 71

2 Answers2

191

Unlike other languages such as C/C++, in PHP you can use the optional param of break like this:

break 2;

In this case if you have two loops such that:

while(...) {
   while(...) {
      // do
      // something

      break 2; // skip both
   }
}

break 2 will skip both while loops.

Doc: http://php.net/manual/en/control-structures.break.php

This makes jumping over nested loops more readable than for example using goto of other languages

dynamic
  • 46,985
  • 55
  • 154
  • 231
  • 9
    And it is almost as evil as goto :-) (+1 anyway) – zerkms Jul 23 '12 at 09:15
  • 1
    @zerkms: i don't think... break its prettty readable – dynamic Jul 23 '12 at 09:16
  • 4
    `break` - yes. `break 2` - no :-) – zerkms Jul 23 '12 at 09:16
  • 5
    @zerkms Can you tell us WHY it's evil? Just saying it doesn't really help me understand why I shouldn't use it – dKen Jan 24 '14 at 13:16
  • 12
    @dKen: break 2; isn't evil use it with good indentation and no one will have problems to read your code. Other options are: (i) rewrite the code structure to avoid the use of break 2 and (ii) use of goto. Considering this alternative, `break 2` is the perfectly fine – dynamic Jan 24 '14 at 14:53
  • 3
    I didn't know this thing existed. – mimoralea May 26 '14 at 18:58
  • 4
    `goto` isn't evil. dumb people regurgitate stupidity. – r3wt Nov 08 '14 at 07:24
  • @r3wt if `goto` isn't evil why in PHP documentations you have that very funny story (images) at the top? http://php.net/manual/en/control-structures.goto.php ??? :) – Roy Shoa Apr 20 '17 at 06:32
  • @RoyShoa `goto` can be used responsibly. a good use case in my experience as far as php is concerned, is avoiding the overhead of recursion, like so: https://postimg.org/image/qrlev2elp/ – r3wt Apr 20 '17 at 17:21
  • Obligatory reference: [Go To Considered Harmful](http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html). Basically, `goto` almost always harms program readability / understand-ability, and is always logically unnecessary. – Nathan Arthur Apr 03 '18 at 13:18
  • 1
    Obligatory reference: ["GOTO Considered Harmful" Considered Harmful](http://web.archive.org/web/20090320002214/http://www.ecn.purdue.edu/ParaMount/papers/rubin87goto.pdf). Basically, *not* using `goto` when it makes sense can lead to spaghetti code, and is sometimes logically unnecessary. – Yay295 May 07 '20 at 19:42
  • I commend you for remembering something we must have all read about way back when and immediately forgot! :-) And it's much more readable than inserting extra conditions to check if the inner loop completed. – DRosenfeld Dec 06 '22 at 08:20
3

Use a while loop

<?php 
$count = $i = 0;
while ($count<5 && $query->posts[$i]) {
    $j = 0;
    $post = $query->posts[$i++];
    if ($images = get_children(array(
                    'post_parent' => $post->ID,
                    'post_type' => 'attachment',
                    'post_mime_type' => 'image'))
            ){              
              while ($count < 5 && $images[$j]) { 
                $count++; 
                $image = $images[$j++];
                    ..
                }               
            }
}
?>
periklis
  • 10,102
  • 6
  • 60
  • 68