我想在变量中使用foreach
循环,但这个变量可以是多种不同的类型,例如NULL
。
所以在foreach
之前我测试一下:
if(is_array($var)){
foreach($var as ...
但我意识到它也可以是一个实现Iterator
接口的类。也许我是盲人,但如何检查类是否实现接口?有is_a
函数或inherits
运算符吗?我发现class_implements
,我可以使用它,但也许有更简单的东西?
第二,更重要的是,我认为这个函数存在,足以检查变量is_array
或“实现Iterator
接口”还是应该测试更多的东西?
答案 0 :(得分:68)
如果你在函数中使用foreach
并且你期望一个数组或Traversable对象,你可以输入提示函数:
function myFunction(array $a)
function myFunction(Traversable)
如果你没有在函数中使用foreach
,或者你期望you can simply use this construct检查你是否可以迭代变量:
if (is_array($a) or ($a instanceof Traversable))
答案 1 :(得分:12)
foreach
可以处理数组和对象。您可以通过以下方式查看:
$can_foreach = is_array($var) || is_object($var);
if ($can_foreach) {
foreach ($var as ...
}
您不需要专门检查Traversable
,因为其他人已经在答案中暗示了它,因为所有对象(如所有数组)都可以在PHP中遍历。
更专业:
foreach
适用于所有类型的遍历,即使用数组,使用普通对象(遍历可访问属性)和Traversable
对象(或者更确切地说定义内部get_iterator
的对象处理程序)。
(source)
简单地说,在常见的PHP编程中,只要变量是
和不是
您可以在其上使用 foreach
。
答案 2 :(得分:5)
您可以使用简单的功能检查Traversable
的实例。这适用于Iterator
的所有这一切,因为Iterator extends Traversable
function canLoop($mixed) {
return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}
答案 3 :(得分:2)
<?php
$var = new ArrayIterator();
var_dump(is_array($var), ($var instanceof ArrayIterator));
返回bool(false)
或bool(true)
答案 4 :(得分:1)
PHP 7.1.0 has introduced iterable
pseudo-type and the is_iterable()
function,专为此目的而设计:
这个 […] 提出了一个新的 b = np.insert(a, slice(0,2), a, 2)
b = np.insert(b, slice(0,2), b, 1)
b = np.insert(b, slice(0,2), b, 0)
伪类型。这种类型类似于 array([[[ 1, 1, 2, 2],
[ 1, 1, 2, 2],
[-2, -2, -1, -1],
[-2, -2, -1, -1]],
[[ 1, 1, 2, 2],
[ 1, 1, 2, 2],
[-2, -2, -1, -1],
[-2, -2, -1, -1]],
[[ 3, 3, -4, -4],
[ 3, 3, -4, -4],
[ 4, 4, -3, -3],
[ 4, 4, -3, -3]],
[[ 3, 3, -4, -4],
[ 3, 3, -4, -4],
[ 4, 4, -3, -3],
[ 4, 4, -3, -3]]])
,接受多种类型而不是单一类型。
a
接受任何 for axis in range(3):
a = np.insert(a, slice(0,2), a, axis)
或实现 iterable
的对象。这两种类型都可以使用 callable
进行迭代,并且可以在生成器中与 iterable
一起使用。
array
<块引用>
这个 […] 还添加了一个函数 Traversable
,它返回一个布尔值:foreach
如果一个值是可迭代的并且将被 yield
伪类型接受,{{1} } 用于其他值。
function foo(iterable $iterable) {
foreach ($iterable as $value) {
// ...
}
}
您也可以使用函数 is_iterable()
来检查传递的变量是否为数组:
true
答案 5 :(得分:0)
<?php
/**
* Is Array?
* @param mixed $x
* @return bool
*/
function isArray($x) : bool {
return !isAssociative($x);
}
/**
* Is Associative Array?
* @param mixed $x
* @return bool
*/
function isAssociative($x) : bool {
if (!is_array($array)) {
return false;
}
$i = count($array);
while ($i > 0) {
if (!isset($array[--$i])) {
return true;
}
}
return false;
}
<?php
$arr = [ 'foo', 'bar' ];
$obj = [ 'foo' => 'bar' ];
var_dump(isAssociative($arr));
# bool(false)
var_dump(isAssociative($obj));
# bool(true)
var_dump(isArray($obj));
# bool(false)
var_dump(isArray($arr));
# bool(true)
答案 6 :(得分:0)
自PHP 7.1起,就有一个伪类型iterable
用于此目的。类型提示iterable
接受任何数组以及Traversable
接口的任何实现。 PHP 7.1还引入了功能is_iterable()
。对于较旧的版本,请参见此处的其他答案,以在没有较新的内置功能的情况下完成等效类型的强制实施。
公平竞争:正如BlackHole所指出的那样,这个问题似乎是Iterable objects and array type hinting?的重复,而his or her answer的细节比我的还要详细。