可变对象和数组类型提示?

use*_*841 53 php iterator type-hinting

我有很多函数要么为数组提供类型提示,要么用于is_array()检查变量的数组.

现在我开始使用可迭代的对象.他们实施IteratorIteratorAggregate.如果它们通过类型提示或经历,它们会被接受为数组is_array()吗?

如果我必须修改我的代码,是否有一般类型is_iterable(),或者我必须做类似的事情:

if ( is_array($var) OR $var instance_of Iterable OR $var instanceof IteratorAggregate ) { ... }
Run Code Online (Sandbox Code Playgroud)

还有哪些可迭代的接口?

Nul*_*ion 75

我认为你的意思是instanceof Iterator,PHP没有Iterable接口.它确实有一个Traversable界面.Iterator并且IteratorAggregate两者都延伸Traversable(和AFAIK他们是唯一这样做的).

但不,实现的对象Traversable不会通过is_array()检查,也没有内置is_iterable()函数.你可以使用的支票是

function is_iterable($var) {
    return (is_array($var) || $var instanceof Traversable);
}
Run Code Online (Sandbox Code Playgroud)

要清楚,所有 php对象都可以使用foreach进行迭代,但只有部分可以实现Traversable.因此,所呈现的is_iterable函数将不会检测到foreach可以处理的所有事物.

  • `Iterator`和`IteratorAggregate`没有实现`Traversable`.它们是接口,因此没有实现.他们*扩展*`Traversable`.除此之外,+1 (23认同)
  • `foreach`将用于不是那些接口实例的类.它只是迭代实例的所有属性.如果你想要自定义行为,你必须实现`Iterator` (6认同)
  • @NullUserException 因为 PHP7.1 已经实现了 `is_iterable` 函数,你应该在你的示例代码中添加和 `if function_exists(...)` (4认同)
  • PHP现在具有伪类型iterable(7.1).:-D (3认同)

Bla*_*ole 27

PHP 7.1.0 引入iterable伪类型和is_iterable()函数,它是专门为此目的而设计的:

这[...]提出了一种新的iterable伪类型.这种类型类似于callable,接受多种类型而不是单一类型.

iterable接受任何array或实施的对象Traversable.这两种类型都foreach可以使用迭代,并且可以yield在生成器中使用.

function foo(iterable $iterable) {
    foreach ($iterable as $value) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这[...]还添加了一个is_iterable()返回布尔值的函数:true如果值是可迭代的,并且iterable伪类型将接受false其他值.

var_dump(is_iterable([1, 2, 3])); // bool(true)
var_dump(is_iterable(new ArrayIterator([1, 2, 3]))); // bool(true)
var_dump(is_iterable((function () { yield 1; })())); // bool(true)
var_dump(is_iterable(1)); // bool(false)
var_dump(is_iterable(new stdClass())); // bool(false)
Run Code Online (Sandbox Code Playgroud)


Isa*_*aac 12

我实际上不得不为stdClass添加一个检查,因为stdClass的实例在foreach循环中起作用,但是stdClass没有实现Traversable:

function is_iterable($var) {
    return (is_array($var) || $var instanceof Traversable || $var instanceof stdClass);
}
Run Code Online (Sandbox Code Playgroud)

  • 所有对象都可以"foreach",但这样做往往是无意的. (9认同)
  • 并非所有对象都是`instanceof stdClass`,但正如@Brilliand指出的那样,所有对象都可以是'foreach`.在许多情况下,你会检查你是否真的想要'foreach`它,就像在`is_array($ var)`返回true或者`$ var instanceof Traversable`返回true时.如果你真的想在任何可以"预测"的东西上运行`foreach`(只要你意识到你正在做什么以及为什么这样做就没有错),那么你最好更换掉最后一部分使用`is_object($ var)`的代码 (2认同)
  • 更新:从 PHP7.1 开始,一个原生的 [```is_iterable()```](http://php.net/manual/en/function.is-iterable.php) 函数可用。 (2认同)