Voitcus
Voitcus

Reputation: 4456

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

I want to use a foreach loop with a variable, but this variable can be many different types, NULL for example.

So before foreach I test it:

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

But I realized that it can also be a class that implements Iterator interface. Maybe I am blind but how to check whether the class implements interface? Is there something like is_a function or inherits operator? I found class_implements, I can use it, but maybe there is something simpler?

And second, more important, I suppose this function exist, would be enough to check if the variable is_array or "implements Iterator interface" or should I test for something more?

Upvotes: 96

Views: 169539

Answers (7)

thomas
thomas

Reputation: 915

PHP 7.1.0 has introduced the iterable 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?

Upvotes: 3

faintsignal
faintsignal

Reputation: 1836

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.

Upvotes: 0

Alexey
Alexey

Reputation: 3484

<?php
$var = new ArrayIterator();

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

returns bool(false) or bool(true)

Upvotes: 2

Eduardo Cuomo
Eduardo Cuomo

Reputation: 19016

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)

Upvotes: 0

Shoe
Shoe

Reputation: 76298

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

Upvotes: 90

hakre
hakre

Reputation: 198249

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.

Upvotes: 16

Baba
Baba

Reputation: 95161

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

Upvotes: 5

Related Questions