How to use foreach loops in PHP 8

Collections, sets, arrays are the bedrock of any information system. Therefore it is not surprising that developers want to iterate over these data structures to do a search, mutation or calculation. Luckily, PHP 8 offers a simple control flow statement called foreach loop to do all sorts of operations with your data.

In PHP 8 you can use foreach loops to loop through arrays and objects but you can not use it on any other data type like uninitialized variables, strings or scalar data types. These include booleans, integers, floats and strings.

The basic syntax of the construct consists of a head which defines what you want to loop through and a body that defines what you want to do for every component in the data structure.

Let's start with the head. Just like with regular function definitions in the PHP language, you define the variables that you'd like to operate on. Essentially, there are 3 possible variables supported by the foreach statement whereby 2 are mandatory. These are:

To make things clearler, let's look a simple example with just the mandatory parts:

foreach($subject as $current) {

}

In comparison, this is a foreach loop syntax with all three components:

foreach($subject as $index => $current) {

}

Looking at these 2 examples, we see two extra syntactic components. The as and the arrow =>. The as instructs the foreach loop to use the variable to its left as the subject to iterate over. The part on the right side of the as are variables that the foreach statement provides as handles for the current position inside of the subject so that you can access them in the body of the foreach loop. The accessors can either be just the value at the current position or the key defining the position of the value preceding the arrow =>.

As for the body, you can put any operations inside of the body. Additionally you have at your disposal special instruction keywords that allow you to skip ahead or cancel the loop. For jumping to the next iteration, you would use the instruction continue and for aborting the foreach loop the instruction break. They are handy if you wanted to iterate over an associative array to look for something. As soon as you have found the desired item, you'd stop the foreach loop to improve the performance of your program. You would use the continue instruction if you wanted to do an operation only on certain items that satisfy a condition. If they didn't, you would use continue to skip ahead.

foreach($subject as $current) {
    if ($current > 10) {
        continue;
    }

    print $current;
}

foreach($subject as $current) {
    if ($current > 10) {
        break;
    }

    print $current;
}

Possible pitfalls with foreach loops

Having the ability to use references in PHP can make using foreach loops a source of bugs. Let's look at an example.

$subject = [1, 2, 3];

foreach($subject as &$current) {
    print $current;
}

foreach($subject as $current) {
    print $current;
}

Outputs: 123122

Looking at the output, we can see that in the second foreach loop the values change inside of the subject even though we are only printing the output. Unfortunately, PHP 8 and earlier version see the $current variable as one and the same as the variable is scoped to the enclosing block. Unfortunately, you can't introduce an additional scope or restrict it. Therefore you need to be aware of this property in the PHP language and make sure to unset the variables should you use references in foreach loops.

Essentially what happend is: with each iteration in the second foreach loop, the last value in $subject gets updated via the still active &$current reference. So the subject would look after each iteration like this: [1, 2, 1], [1, 2, 2], [1, 2, 2]. Obvisouly this behavior is not intended and while programming you have to pay special attention to these sideeffects.