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


90

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

因此,在foreach测试之前:

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

但是我意识到它也可以是实现Iterator接口的类。也许我是盲人,但如何检查该类是否实现了接口?是否有类似is_a函数或inherits运算符的内容?我发现了class_implements,我可以使用它,但是也许有更简单的东西吗?

其次,更重要的是,我想这个功能是否存在,足以检查变量is_array或“实现Iterator接口”,还是应该测试更多功能?


2
if($ var instanceof ArrayIterator)
Alexey

是的,我非常确定这是行不通的,甚至没有看过手册...
Voitcus

Answers:


79

如果foreach在函数内部使用并且期望数组或Traversable对象,则可以使用以下命令键入该函数的提示:

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

如果您不在foreach函数内部使用,或者期望两者都使用,则可以简单地使用此构造来检查是否可以遍历变量:

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

谢谢。我希望已经足够,并且没有/将没有其他语言结构可以迭代。
Voitcus

我发现is_array很贵。计算成本似乎随着数组的大小而增加(这没有任何意义,因为它只是检查它是否是数组)。但这件事在图书馆令我震惊。请参阅链接问题中的我的评论。将instanceof Traversable使用数组?我没有机会测试其性能。
ADTC

@ADTC AFAIR数组是Traversableso 的实例。

1
@Shoe我在这里尝试。随着$var = array(1,2,3);结果是:is_array($var) = true$var instanceof Traversable = false
ADTC

@ADTC是的,刚刚检查过。数组无法实现Iterator,因此无法使用Traversable

15

foreach可以处理数组和对象。您可以使用以下方法进行检查:

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

您不需要专门检查Traversable其他人是否在答案中暗示了这一点,因为所有对象(如所有数组)都可以在PHP中遍历。

从技术上讲:

foreach适用于各种可遍历对象,即数组,普通对象(遍历可访问属性的Traversable对象)和对象(或定义内部get_iterator处理程序的对象)。

来源

在普通的PHP编程中简单地说,只要变量是

  • 数组
  • 一个东西

而且不是

  • 空值
  • 资源
  • 标量

您可以使用foreach它。


5

您可以Traversable使用简单的功能检查的实例。这将对所有这些都起作用,Iterator因为Iterator extends Traversable

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

“?true:false”部分是多余的。instanceof已经给出了布尔值。
利纳斯

2
<?php
$var = new ArrayIterator();

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

返回bool(false)bool(true)


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)

0

从PHP 7.1开始,有一个伪类型iterable用于此目的。类型提示iterable接受任何数组以及Traversable接口的任何实现。PHP 7.1还引入了该功能is_iterable()。对于较旧的版本,请参见此处的其他答案,以在没有较新的内置功能的情况下完成等效的类型强制实施。

公平竞争:正如BlackHole所指出的,这个问题似乎是Iterable对象和数组类型提示的重复他或她的答案进入更详细的比我的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.