php8.5
Home/ Manual/ migration70 / incompatible/ Changes to Foreach

Changes to Foreach

Minor changes have been made to the behaviour of the Foreach control structure, primarily around the handling of the internal array pointer and modification of the array being iterated over.

Minor changes have been made to the behaviour of the Foreach control structure, primarily around the handling of the internal array pointer and modification of the array being iterated over.

Foreach no longer changes the internal array pointer

Prior to PHP 7, the internal array pointer was modified while an array was being iterated over with Foreach. This is no longer the case, as shown in the following example:

php
<?php
$array = [0, 1, 2];
foreach ($array as &$val) {
    var_dump(current($array));
}
?>

5

output
int(1)
int(2)
bool(false)

7

output
int(0)
int(0)
int(0)

Foreach by-value operates on a copy of the array

When used in the default by-value mode, Foreach will now operate on a copy of the array being iterated rather than the array itself. This means that changes to the array made during iteration will not affect the values that are iterated.

Foreach by-reference has improved iteration behaviour

When iterating by-reference, Foreach will now do a better job of tracking changes to the array made during iteration. For example, appending to an array while iterating will now result in the appended values being iterated over as well:

php
<?php
$array = [0];
foreach ($array as &$val) {
    var_dump($val);
    $array[1] = 1;
}
?>

5

output
int(0)

7

output
int(0)
int(1)

Iteration of non-Traversable objects

Iterating over a non-Traversable object will now have the same behaviour as iterating over by-reference arrays. This results in the improved behaviour when modifying an array during iteration also being applied when properties are added to or removed from the object.

Source: appendices/migration70/incompatible/foreach.xml · from the official PHP manual (php/doc-en)