is_iterable()
The is_iterable() function is a built-in function in PHP 7.1 and above that checks whether a variable is iterable or not. An iterable is a data type that can be
Introduction
is_iterable() is a built-in PHP function (available since PHP 7.1) that tells you whether a value can be looped over with a foreach loop. It returns true for exactly two kinds of values:
- Arrays — every array is iterable.
- Objects that implement the
Traversableinterface — in practice this means objects implementingIteratororIteratorAggregate, as well as generators (functions that useyield).
Everything else — strings, integers, booleans, null, and plain objects (like stdClass) — is not iterable, even if it intuitively feels "list-like". This page covers the syntax, what counts as iterable, the most common gotchas, and when reaching for is_iterable() actually pays off.
Syntax
is_iterable(mixed $value): boolIt takes a single argument, $value, and returns a boolean:
| Argument | Result |
|---|---|
| An array | true |
A Traversable object (Iterator, IteratorAggregate, generator) | true |
Anything else (string, int, plain object, null, …) | false |
Since PHP 8.0 there is also a matching pseudo-type, iterable, that you can use as a type declaration — see When to use it below.
Basic example
$var1 is an array, so it is iterable. $var2 is a string — even though you can index into a string character by character, you cannot drive it with foreach, so is_iterable() returns false.
What counts as iterable
The interesting cases are objects. An object is only iterable if it implements Traversable (directly or via Iterator/IteratorAggregate), or if it is a generator. A plain object is not.
<?php
function genFn() {
yield 1;
yield 2;
}
class MyCollection implements IteratorAggregate {
private array $items = [1, 2, 3];
public function getIterator(): Iterator {
return new ArrayIterator($this->items);
}
}
var_dump(is_iterable([1, 2, 3])); // bool(true) array
var_dump(is_iterable(genFn())); // bool(true) generator
var_dump(is_iterable(new MyCollection())); // bool(true) Traversable
var_dump(is_iterable("hello")); // bool(false) string
var_dump(is_iterable(42)); // bool(false) int
var_dump(is_iterable(new stdClass())); // bool(false) plain object
var_dump(is_iterable(null)); // bool(false) null
?>The key takeaway: a stdClass (or any object without Traversable) returns false, even though foreach can loop over its public properties. is_iterable() deliberately reports only values that are iterable by contract, not by accident.
Common gotchas
- Strings are not iterable. A string is a scalar, not a collection, so
is_iterable("abc")isfalse. To check for a string, useis_string()instead. - Plain objects fail.
is_iterable(new stdClass())isfalse. If you only want to know whether a value is any object, useis_object(); if you specifically need a loopable object,is_iterable()is the right call. - It is not the same as
is_array().is_array()istrueonly for arrays and rejects generators andTraversableobjects. Useis_iterable()when you want to accept both arrays and iterator objects. nullreturnsfalse. Passing an uninitialized ornullvalue is safe — it simply returnsfalserather than raising an error.
When to use it
Use is_iterable() as a guard clause before a foreach, so a function can accept either an array or a lazy iterator without blowing up on bad input:
<?php
function sumAll(mixed $data): int {
if (!is_iterable($data)) {
throw new InvalidArgumentException('Expected an iterable.');
}
$total = 0;
foreach ($data as $value) {
$total += $value;
}
return $total;
}
echo sumAll([1, 2, 3, 4]), "\n"; // 10
function counter() {
yield 5;
yield 10;
}
echo sumAll(counter()), "\n"; // 15
?>The same function handles a plain array and a generator, because both satisfy is_iterable().
Often the cleaner choice is the iterable type declaration (PHP 7.1+), which lets PHP enforce the constraint for you so you can skip the manual check entirely:
<?php
function sumAll(iterable $data): int {
$total = 0;
foreach ($data as $value) {
$total += $value;
}
return $total;
}
?>Reach for the is_iterable() function when the value is mixed and you want to branch at runtime; reach for the iterable type hint when iterability is a hard requirement of the parameter.
Conclusion
is_iterable() answers one precise question: can this value be driven by a foreach loop? It returns true for arrays and Traversable objects (including generators) and false for everything else. Use it as a runtime guard for mixed inputs, prefer the iterable type hint when iterability is mandatory, and remember it is stricter than it looks — strings and plain objects are not iterable. For related checks, see is_array(), is_object(), and gettype().