我想使用带有变量的foreach
循环,但这个变量可以是许多不同的类型,例如NULL
。
所以在foreach
之前,我测试它:
if(is_array($var)){
foreach($var as ...
但我意识到它也可以是一个实现Iterator
接口的类。也许我是盲人,但如何检查类是否实现了接口?有类似is_a
函数或inherits
运算符的东西吗?我找到了class_implements
,我可以使用它,但也许还有更简单的东西?
第二,更重要的是,我认为这个函数存在,足以检查变量is_array
或"实现Iterator
接口",或者我应该测试更多的东西吗?
如果您在函数中使用foreach
,并且您需要一个数组或Traversable对象,则可以使用以下命令键入提示该函数:
function myFunction(array $a)
function myFunction(Traversable)
如果你没有在函数中使用foreach
,或者你期望两者都使用,你可以简单地使用这个构造来检查你是否可以迭代变量:
if (is_array($a) or ($a instanceof Traversable))
foreach
可以处理数组和对象。您可以使用进行检查
$can_foreach = is_array($var) || is_object($var);
if ($can_foreach) {
foreach ($var as ...
}
您不需要像其他人在回答中暗示的那样专门检查Traversable
,因为所有对象——就像所有数组一样——都可以在PHP中遍历。
更技术化:
foreach
适用于所有类型的可遍历对象,即数组、普通对象(其中遍历可访问属性(和Traversable
对象(或者更确切地说,定义内部get_iterator
处理程序的对象(。
(来源(
简单地说,在常见的PHP编程中,只要变量是
- 数组
- 物体
不是
- NULL
- 资源
- 标量
您可以在上面使用foreach
。
您可以使用一个简单的函数来检查Traversable
的实例。这将适用于Iterator
的所有这些,因为Iterator extends Traversable
function canLoop($mixed) {
return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}
<?php
$var = new ArrayIterator();
var_dump(is_array($var), ($var instanceof ArrayIterator));
返回bool(false)
或bool(true)
PHP 7.1.0引入了iterable
伪类型和is_iterable()
函数,它是专门为这样一个目的而设计的:
本文提出了一种新的CCD_ 25伪类型。这种类型类似于
callable
,接受多个类型而不是一个单一类型。CCD_ 27接受任何CCD_ 28或实现CCD_ 29的对象。这两种类型都可以使用
foreach
进行迭代,并且可以在生成器内与yield
一起使用。
function foo(iterable $iterable) {
foreach ($iterable as $value) {
// ...
}
}
这个[…]还添加了一个函数
is_iterable()
,它返回一个布尔值:如果一个值是可迭代的,并且将被iterable
伪类型接受,则返回true
;对于其他值,返回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)
您也可以使用函数is_array($var)
来检查传递的变量是否是数组:
<?php
var_dump( is_array(array()) ); // true
var_dump( is_array(array(1, 2, 3)) ); // true
var_dump( is_array($_SERVER) ); // true
?>
阅读如何在PHP中检查变量是否为数组?
函数
<?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)
由于PHP 7.1,有一个伪类型iterable
正是用于此目的。类型提示iterable
接受任何数组以及Traversable
接口的任何实现。PHP 7.1还引入了函数CCD_ 40。对于较旧的版本,请参阅此处的其他答案,以在不使用较新的内置功能的情况下实现等效的类型强制。
公平竞争:正如BlackHole所指出的,这个问题似乎是Iterable对象和数组类型暗示的重复他或她的回答比我的更详细。