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.

Tadas
  • 331
  • 1
  • 7
  • I've tried that, you're right. When you use array without ArrayIterator it works. There's no deprecation note inside the docs. – cssBlaster21895 Sep 30 '20 at 10:26
  • 1
    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: https://www.php.net/ChangeLog-7.php – Bossman Sep 30 '20 at 10:37
  • I see a deprecation for `ArrayObject` but not for this .See the [reference](https://raw.githubusercontent.com/php/php-src/PHP-7.4/UPGRADING), search for SPL section – Dark Knight Sep 30 '20 at 10:39
  • With a bit of bisecting, the culprit is https://github.com/php/php-src/commit/a5fa51afbbd87bedeb1c5fd7c9a6cf3c971ab14c#diff-a84ed8c7e86da360bb911990cf291d04 – msbit Sep 30 '20 at 16:54

2 Answers2

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

Tomáš Fejfar
  • 11,129
  • 8
  • 54
  • 82
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.

yarns
  • 66
  • 8