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

PhpArraysForeach

Php Problem Overview


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?

Php Solutions


Solution 1 - Php

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

Solution 2 - Php

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.

Solution 3 - Php

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

Solution 4 - Php

<?php
$var = new ArrayIterator();

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

returns bool(false) or bool(true)

Solution 5 - Php

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?

Solution 6 - Php

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)

Solution 7 - Php

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVoitcusView Question on Stackoverflow
Solution 1 - PhpShoeView Answer on Stackoverflow
Solution 2 - PhphakreView Answer on Stackoverflow
Solution 3 - PhpBabaView Answer on Stackoverflow
Solution 4 - PhpAlexeyView Answer on Stackoverflow
Solution 5 - PhpthomasView Answer on Stackoverflow
Solution 6 - PhpEduardo CuomoView Answer on Stackoverflow
Solution 7 - PhpfaintsignalView Answer on Stackoverflow