Cannot iterate over iterator with array_walk since php 7.4

478 views Asked by At
$iterator = new ArrayIterator([1, 2]);
array_walk($iterator, function($item) {echo $item . PHP_EOL;});

This piece of php code outputs the items (1 and 2) in php 7.3 but it outputs nothing in php 7.4. Can anyone explain what changed in php 7.4 that resulted in this change ? I cannot find anything related to that in the changelogs.

2

There are 2 answers

0
Tomáš Fejfar On

Just in case someone needs to work around this, you can convert iterator to array.

$iterator = new ArrayIterator([1, 2]);
$array = iterator_to_array($iterator);
array_walk($array, function($item) {echo $item . PHP_EOL;});

https://3v4l.org/Xq9Dc

0
yarns On

There is no explicit deprecation of this feature (ie array_walk() used on instances of ArrayIterator) however after further investigation I have found that as of PHP7.4, array_walk() will work on the properties of the ArrayIterator and not it's encapsulated array. Although this case is not explicitly stated in the manual, I'm sure this is the reason.

To summarise the manual (Migrating to PHP7.4 > Backward Incompatible Changes > Standard PHP Library (SPL))

Calling get_object_vars() on ArrayObject (and ArrayIterator) returns the properties of the instance, where pre php7.4 it returned the wrapped array. Potentially affected operations are those working on object properties as a list eg array_walk().

so what you're getting is the ArrayIterator instances property list, which is empty because the array is stored in a private property.

Incompatible Changes to PHP7.4 - php.net

Standard PHP Library (SPL)

Calling get_object_vars() on an ArrayObject instance will now always return the properties of the ArrayObject itself (or a subclass). Previously it returned the values of the wrapped array/object unless the ArrayObject::STD_PROP_LIST flag was specified.

Other affected operations are:

  • ReflectionObject::getProperties()
  • reset(), current(), etc. Use Iterator methods instead.
  • Potentially others working on object properties as a list, e.g. array_walk().

(array) casts are not affected. They will continue to return either the wrapped array, or the ArrayObject properties, depending on whether the ArrayObject::STD_PROP_LIST flag is used.