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


How to check if variable is array?... or something array-like

我想使用带有变量的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对象和数组类型暗示的重复他或她的回答比我的更详细。