如何检查变量是否是数组? ... 或类似数组的东西

我想使用一个带有变量的 foreach循环,但是这个变量可以是许多不同的类型,例如 NULL

因此,在 foreach之前,我先测试一下:

if(is_array($var)){
foreach($var as ...

但是我意识到它也可以是一个实现 Iterator接口的类。也许我是盲目的,但是如何检查类是否实现了接口?是否有类似 is_a函数或 inherits操作符的东西?我找到了 class_implements,我可以使用它,但也许有更简单的东西?

其次,更重要的是,我假设这个函数存在,这样就足以检查变量 is_array或“实现 Iterator接口”,还是应该测试更多内容?

151748 次浏览
<?php
$var = new ArrayIterator();


var_dump(is_array($var), ($var instanceof ArrayIterator));

returns bool(false) or bool(true)

You can check instance of Traversable with a simple function. This would work for all this of Iterator because Iterator extends Traversable

function canLoop($mixed) {
return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}

If you are using foreach inside a function and you are expecting an array or a Traversable object you can type hint that function with:

function myFunction(array $a)
function myFunction(Traversable)

If you are not using foreach inside a function or you are expecting both you can simply use this construct to check if you can iterate over the variable:

if (is_array($a) or ($a instanceof Traversable))

foreach can handle arrays and objects. You can check this with:

$can_foreach = is_array($var) || is_object($var);
if ($can_foreach) {
foreach ($var as ...
}

You don't need to specifically check for Traversable as others have hinted it in their answers, because all objects - like all arrays - are traversable in PHP.

More technically:

foreach works with all kinds of traversables, i.e. with arrays, with plain objects (where the accessible properties are traversed) and Traversable objects (or rather objects that define the internal get_iterator handler).

(source)

Simply said in common PHP programming, whenever a variable is

  • an array
  • an object

and is not

  • NULL
  • a resource
  • a scalar

you can use foreach on it.

Functions

<?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;
}

Example

<?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)

Since PHP 7.1 there is a pseudo-type iterable for exactly this purpose. Type-hinting iterable accepts any array as well as any implementation of the Traversable interface. PHP 7.1 also introduced the function is_iterable(). For older versions, see other answers here for accomplishing the equivalent type enforcement without the newer built-in features.

Fair play: As BlackHole pointed out, this question appears to be a duplicate of Iterable objects and array type hinting? and his or her answer goes into further detail than mine.

PHP 7.1.0 has introduced the ABC0 pseudo-type and the is_iterable() function, which is specially designed for such a purpose:

This […] proposes a new iterable pseudo-type. This type is analogous to callable, accepting multiple types instead of one single type.

iterable accepts any array or object implementing Traversable. Both of these types are iterable using foreach and can be used with yield from within a generator.

function foo(iterable $iterable) {
foreach ($iterable as $value) {
// ...
}
}

This […] also adds a function is_iterable() that returns a boolean: true if a value is iterable and will be accepted by the iterable pseudo-type, false for other values.

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)

You can also use the function is_array($var) to check if the passed variable is an array:

<?php
var_dump( is_array(array()) ); // true
var_dump( is_array(array(1, 2, 3)) ); // true
var_dump( is_array($_SERVER) ); // true
?>

Read more in How to check if a variable is an array in PHP?