92

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

所以在foreach我测试它之前:

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

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

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

4

7 回答 7

83

如果您foreach在函数内部使用并且您期望一个数组或Traversable对象,您可以键入提示该函数:

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

如果你没有foreach在函数内部使用或者你期望两者都可以,你可以简单地使用这个结构来检查你是否可以迭代变量:

if (is_array($a) or ($a instanceof Traversable))
于 2013-03-24T21:11:03.417 回答
15

foreach可以处理数组和对象。您可以通过以下方式检查:

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

您不需要Traversable像其他人在他们的答案中暗示的那样专门检查,因为所有对象(如所有数组)都可以在 PHP 中遍历。

从技术上讲:

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

来源

简单地说,在常见的 PHP 编程中,每当一个变量是

  • 数组
  • 一个东西

并且不是

  • 无效的
  • 资源
  • 一个标量

你可以用foreach它。

于 2015-05-25T10:03:27.657 回答
5

Traversable您可以使用简单的函数检查实例。这将适用于所有这些,Iterator因为Iterator extends Traversable

function canLoop($mixed) {
    return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}
于 2013-03-24T21:09:13.827 回答
2
<?php
$var = new ArrayIterator();

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

返回bool(false)bool(true)

于 2013-03-24T21:04:27.770 回答
1

PHP 7.1.0引入iterable伪类型和is_iterable()函数,它们是专门为此目的而设计的:

这 […] 提出了一种新的iterable伪类型。这种类型类似于callable,接受多种类型而不是一种类型。

iterable接受任何array或实现的对象Traversable。这两种类型都是可迭代的,foreach并且可以yield在生成器中使用。

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

这个 […] 还添加了一个is_iterable()返回布尔值的函数:true如果一个值是可迭代的并且将被iterable伪类型接受,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 中的数组?

于 2021-01-08T13:17:13.797 回答
0

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

公平竞争:正如 BlackHole 所指出的,这个问题似乎是Iterable objects 和 array type hinting 的重复?他或她的回答比我的更详细。

于 2018-12-18T00:45:46.560 回答
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)
于 2018-12-18T00:27:22.823 回答