【问题标题】:How to check if variable is array?... or something array-like如何检查变量是否为数组?...或类似数组的东西
【发布时间】:2013-03-14 07:02:43
【问题描述】:

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

所以在foreach之前我测试了一下:

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

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

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

【问题讨论】:

标签: php arrays foreach


【解决方案1】:
<?php
$var = new ArrayIterator();

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

返回bool(false)bool(true)

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • "? true : false" 部分是多余的。 instanceof 已经给出了一个 bool 值作为结果。
    【解决方案3】:

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

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

    如果您没有在函数中使用foreach,或者您希望you can simply use this construct 都检查您是否可以迭代变量:

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

    【讨论】:

    • 谢谢。我希望这已经足够了,并且没有/不会有其他可以迭代的语言结构。
    • 我发现is_array 很贵。计算成本似乎随着数组的大小而增加(这没有任何意义,因为它只是检查它是否是一个数组)。但它在图书馆里让我震惊地发生了。请参阅链接问题中的my commentinstanceof Traversable 可以处理数组吗?我没有机会测试它的性能。
    • @ADTC AFAIR 数组是Traversable 的一个实例,所以是的。
    • @Shoe 我试过了here$var = array(1,2,3); 的结果是:is_array($var) = true$var instanceof Traversable = false
    • @ADTC 是的,刚刚检查过。数组不实现Iterator,因此不适用于Traversable
    【解决方案4】:

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

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

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

    从技术上讲:

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

    (source)

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

    • 一个数组
    • 一个对象

    不是

    • 资源
    • 标量

    你可以在上面使用foreach

    【讨论】:

      【解决方案5】:

      功能

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

      【讨论】:

        【解决方案6】:

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

        公平竞争:正如 BlackHole 指出的那样,这个问题似乎与 Iterable objects and array type hinting? 重复,his or her answer 比我的更详细。

        【讨论】:

          【解决方案7】:

          PHP 7.1.0 has introduced iterable pseudo-type and the is_iterable() function,专门为此目的设计的:

          这个 […] 提出了一个新的 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
          ?>
          

          阅读更多How to check if a variable is an array in PHP?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-03-28
            • 1970-01-01
            • 2010-10-26
            • 1970-01-01
            • 2014-05-12
            相关资源
            最近更新 更多