Cannot iterate over iterator with array_walk since php 7.4
Asked Answered
P

3

13
$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.

Puttier answered 30/9, 2020 at 9:57 Comment(4)
I've tried that, you're right. When you use array without ArrayIterator it works. There's no deprecation note inside the docs.Either
Just to narrow down a bit further. 7.3.19 works, 7.4.0 doesn't. There was a change to the ArrayItterator (#78409) in 7.4.0. Ref: php.net/ChangeLog-7.phpRudolf
I see a deprecation for ArrayObject but not for this .See the reference, search for SPL sectionManualmanubrium
With a bit of bisecting, the culprit is github.com/php/php-src/commit/…Scalf
L
0

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

Lover answered 6/11, 2022 at 19:25 Comment(0)
M
0

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.

Malanie answered 28/6, 2023 at 3:48 Comment(0)
L
0

In PHP 7.4, the behavior of array_walk with objects implementing the Traversable interface, such as ArrayIterator, has changed. In PHP 7.3, array_walk could accept an ArrayIterator directly, but starting from PHP 7.4, array_walk expects an array, and it does not automatically convert Traversable objects to arrays.

To fix this issue in PHP 7.4 and later, you need to explicitly convert the ArrayIterator to an array before passing it to array_walk:

$iterator = new ArrayIterator([1, 2]);
array_walk(iterator_to_array($iterator), function($item) {
    echo $item . PHP_EOL;
});
Laruelarum answered 28/5, 2024 at 8:7 Comment(1)
Did you create this answer with ChatGPT?Bream

© 2022 - 2025 — McMap. All rights reserved.