$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 中的哪些变化导致了这一变化?我在变更日志中找不到与此相关的任何内容。
以防万一有人需要解决这个问题,您可以将迭代器转换为数组。
$iterator = new ArrayIterator([1, 2]);
$array = iterator_to_array($iterator);
array_walk($array, function($item) {echo $item . PHP_EOL;});
没有明确弃用此功能(即
array_walk()
用于 ArrayIterator
的实例),但是经过进一步调查,我发现从 PHP7.4 开始,array_walk()
将适用于 ArrayIterator
的属性,并且不是它的封装数组。虽然手册中没有明确说明这种情况,但我确信这就是原因。
总结手册(迁移到 PHP7.4 > 向后不兼容更改 > 标准 PHP 库 (SPL))
在
get_object_vars()
(和 ArrayObject
)上调用 ArrayIterator
返回实例的属性,在 php7.4 之前它返回包装数组。潜在受影响的操作是那些以列表形式处理对象属性的操作,例如 array_walk()
。
所以你得到的是
ArrayIterator
实例属性列表,它是空的,因为数组存储在私有属性中。
标准 PHP 库 (SPL)
在
实例上调用get_object_vars()
现在将始终返回ArrayObject
本身(或子类)的属性。以前,除非指定了ArrayObject
标志,否则它返回包装数组/对象的值。ArrayObject::STD_PROP_LIST
其他受影响的操作有:
ReflectionObject::getProperties()
、reset()
等。请改用current()
方法。Iterator
- 其他人可能会以列表的形式处理对象属性,例如
。array_walk()
演员不受影响。它们将继续返回包装数组或(array)
属性,具体取决于是否使用ArrayObject
标志。ArrayObject::STD_PROP_LIST
在 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;
});