I want to use a foreach
loop with a variable, but this variable can be many different types, NULL
for example.
So before foreach
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.
<?php
$var = new ArrayIterator();
var_dump(is_array($var), ($var instanceof ArrayIterator));
returns bool(false)
or bool(true)
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))
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;
}
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) andTraversable
objects (or rather objects that define the internalget_iterator
handler).
(source)
Simply said in common PHP programming, whenever a variable is
and is not
you can use foreach
on it.
<?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)