自 php 7.4 起无法使用 array_walk 迭代迭代器

问题描述 投票:0回答:3
$iterator = new ArrayIterator([1, 2]);
array_walk($iterator, function($item) {echo $item . PHP_EOL;});

这段 php 代码在 php 7.3 中输出项目(1 和 2),但在 php 7.4 中不输出任何内容。谁能解释一下 php 7.4 中的哪些变化导致了这一变化?我在变更日志中找不到与此相关的任何内容。

php iterator array-walk
3个回答
0
投票

以防万一有人需要解决这个问题,您可以将迭代器转换为数组。

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

https://3v4l.org/Xq9Dc


0
投票

没有明确弃用此功能(即

array_walk()
用于
ArrayIterator
的实例),但是经过进一步调查,我发现从 PHP7.4 开始,
array_walk()
将适用于
ArrayIterator
的属性,并且不是它的封装数组。虽然手册中没有明确说明这种情况,但我确信这就是原因。

总结手册(迁移到 PHP7.4 > 向后不兼容更改 > 标准 PHP 库 (SPL))

get_object_vars()
(和
ArrayObject
)上调用
ArrayIterator
返回实例的属性,在 php7.4 之前它返回包装数组。潜在受影响的操作是那些以列表形式处理对象属性的操作,例如
array_walk()

所以你得到的是

ArrayIterator
实例属性列表,它是空的,因为数组存储在私有属性中。

对 PHP7.4 的不兼容更改 - php.net

标准 PHP 库 (SPL)

get_object_vars()
实例上调用
ArrayObject
现在将始终返回
ArrayObject
本身(或子类)的属性。以前,除非指定了
ArrayObject::STD_PROP_LIST
标志,否则它返回包装数组/对象的值。

其他受影响的操作有:

  • ReflectionObject::getProperties()
  • reset()
    current()
    等。请改用
    Iterator
    方法。
  • 其他人可能会以列表的形式处理对象属性,例如
    array_walk()

(array)
演员不受影响。它们将继续返回包装数组或
ArrayObject
属性,具体取决于是否使用
ArrayObject::STD_PROP_LIST
标志。


0
投票

在 PHP 7.4 中,array_walk 的行为与实现 可遍历接口(例如 ArrayIterator)已发生变化。在 PHP 7.3 中, array_walk 可以直接接受 ArrayIterator,但从 PHP 7.4,array_walk 需要一个数组,但它不会自动 将 Traversable 对象转换为数组。

要在 PHP 7.4 及更高版本中修复此问题,您需要显式转换 在将数组传递给 array_walk 之前将 ArrayIterator 转换为数组:

$iterator = new ArrayIterator([1, 2]);
array_walk(iterator_to_array($iterator), function($item) {
    echo $item . PHP_EOL;
});
© www.soinside.com 2019 - 2024. All rights reserved.