2
votes

I have a foreach loop inside another foreach loop as this code:

foreach($array1 as $uid => $somevalues) {

  $status = true;
  foreach($somevalues as $somevalue)
    if(!isset($somevalue->$someothervalue))
      $status = false;

  if($status) {
    $content .= "some content added";
    $count++;
  }
}

How it works

As you see I am looping through all entries in $array1. For each entry I loop through the contained $somevalues array to look for a certain condition (that $someothervalue exists there). Now, if this condition (that something isset) is not true then the $status changes to false.

Only if the $status is still true after all loops of the inner foreach, I wish some action to be made (some content added to a text string $content and a raised counter).

The goal

The arrays I'm working with can be quite large and I have been looking at the break and continue commands to try to skip unnecessary parts to improve the code and have the script running through fewer loops.

As you can see, if a loop from the inner foreach results in $status=false then we can stop it right there (no further loops here are necessary). The break is good for this to skip the rest of the forearch loops.

If this is the case then we can also skip the rest of the current outer loop from the outer foreach, since there will not be run any code now that $status is false. For this purpose the continue command would be useful to let us skip the rest of the current outer loop and go on to the next array row right away.

The question

I have been looking at the command lines break 2 and continue 2 e.g. that let you skip the current AND the outer loop (two steps up) with their respective results (either stopping the loop entirely or skipping the rest of current loop). They work as double break - as a "break break" - and as double continue - as a "continue continue" - respectively.

But here I need something like break continue instead, if you get my point. The first loop should break, the next should continue. I am trying to avoid reaching the if statement in the code if not necessary. The check is already made and it feels like doing an unnecessary double check.

I hope the question is clear. Is there a method for this purpose to double skip from within the inner foreach but with the effect of two different commands break continue?

3
The problem with that is that when you exit the inner loop you do not know why it stopped. Was it because you ran through the entire array or because you reached a break statement? Therefore you do have to make the second check outside the inner loop to figure out what action to take. I do now think that by using iterations you can reach the effect of a "break continue" as you stated. - Vinícius Barros
Another approach would be using an external function to run the inner loop and simply return false when your value is not set. But functions may cost a little too much considering that you said your array contains several items and performance is paramount. - Vinícius Barros
Thank you @Vinicius Barros. Yes, creating a function to catch the return is something I did not think of. But it might be too heavy compared to simply keeping the current if way, as you mention. - Steeven

3 Answers

2
votes

"Flag" variables are mostly a code smell, and an indication that you actually should be using a function:

function all_valid($somevalues) {
    foreach($somevalues as $somevalue)
       if(!isset($somevalue->$someothervalue))
           return false;
    return true;
}


foreach($array1 as $uid => $somevalues) {
    if(all_valid($somevalues) {
        do stuff

If you're prepared to sacrifice readability for performance, then how about:

foreach($array1 as $uid => $somevalues) {

    foreach($somevalues as $somevalue)
        if(!isset($somevalue->$someothervalue))
            goto next; // I don't believe I wrote this

    $content .= "some content added";
    $count++;

    next:
}
1
votes

Just use continue 2, it will 'break' out of the first loop and continue the outer loop.

foreach([1, 2, 3] as $i) {
    echo $i . PHP_EOL;

    foreach([4, 5, 6] as $ii) {
        continue 2;
    }

    echo 'this will never print' . PHP_EOL;
}

Will print:

1
2
3
1
votes
foreach($array1 as $uid => $somevalues) {
   // Task of loop 1
   foreach($somevalues as $somevalue){
      // Task of loop 2
      if(!isset($somevalue->$someothervalue))
          {
            continue 2;
            break;
          }
     }
}