为什么对象被认为不可迭代,尽管它们实际上是可迭代的?

5
PHP 7.1新增了新函数is_iterable,用于检查变量是否可以迭代。但是,尽管您可能会迭代对象的属性,但is_iterable对它们返回false。这似乎是有意为之的,因为它已经被记录下来,并且我没有找到任何关于此问题的PHP漏洞,但我想知道为什么要这样做?
<?php
$a = new stdClass();
$a->foo = 'bar';

var_dump(is_iterable($a));

foreach ($a as $key => $value) {
    var_dump($key, $value);
}

输出

boolean false
string 'foo' (length=3)
string 'bar' (length=3)

但我期望它能够输出。
boolean true
string 'foo' (length=3)
string 'bar' (length=3)

虽然被接受的答案是正确的,但它并没有解释为什么他们决定制作一种限制性伪类型,排除了一个非常有效且极其常见的用例。在我看来,无论何处都没有人提供过一个可以遍历数组||可遍历对象但不能遍历对象的代码示例。如果有人能证明这个神秘的用例,我很想在答案中看到它。 - Brad
1个回答

5

这是一个定义问题,“为什么要这样做”是一个棘手的问题,可能更适合PHP开发人员。

但是有些信息:您可以使用foreach遍历对象,并且它将根据手册显示可见属性

PHP 5提供了一种定义对象的方式,以便可以通过列表迭代项,例如foreach语句。默认情况下,所有可见属性都将用于迭代。

is_iterable正在检查特定内容,请参见手册

验证变量的内容是否被可迭代的伪类型接受,即它是数组或实现Traversable的对象

如果您没有自己这样做(并且不是“其他”东西,如数组),则对象不会实现Traversable,因此在那种意义上它不是“可迭代的”。

长话短说:foreach可以迭代任何可迭代的东西,但不是所有foreach可以迭代的东西都被称为可迭代的。这就像椅子有四条腿,但是所有有四条腿的东西都是椅子一样。
我认为你可以在不显式实现可迭代的情况下迭代一个对象是一种例外,就此打住。唯一的其他答案就是“他们这样做是因为……”。

2
这似乎是一条关于 PHP 的回答... 呵呵 ¯\(ツ)/¯。 - deceze
一个对象如果没有自己实现 Traversable 接口,那么它就不会实现 Traversable 接口。这是一个内部引擎接口,无法在 PHP 脚本中实现。死锁了吗? - Alex Blex
2
@Alex 下一句:"必须使用IteratorAggregateIterator中的一个。"(注意:这两个都是Traversable的子类...) - deceze
我不理解在这个检查中排除对象的用例。是否存在一种情况,即可遍历可迭代对象或数组,但不能遍历对象?我们大多数人长期以来想要的是“我可以对此进行foreach”检查,而is_iterable在其当前状态下并未提供此功能。 - Brad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接