PHP Iterables
PHP Iterables, also known as arrays, are data structures that allow you to store and manipulate multiple values in a single variable. These values can be of
Introduction to PHP Iterables
In PHP, an iterable is anything you can loop over with foreach. That includes two kinds of values:
- Arrays — the everyday data structure that holds an ordered collection of key/value pairs.
Traversableobjects — objects that PHP knows how to walk through, because they implement the built-inTraversableinterface (in practice viaIteratororIteratorAggregate, or as a generator).
PHP 7.1 added the iterable pseudo-type so you can declare "give me anything I can foreach over" without caring whether the caller passes an array or an object. This page covers what counts as iterable, how to create and traverse each kind, and when to reach for the lazy iterables that generators give you.
This chapter builds on PHP Arrays and the foreach loop. If you are new to either, read those first.
Arrays: the most common iterable
Arrays come in two flavours, and the only difference is the type of key they use:
- An indexed array stores values under automatic integer keys, starting at
0. See Indexed Arrays. - An associative array uses strings (or integers you choose) as keys. See Associative Arrays.
A single array can mix both styles, and the values can be of any data type.
Creating and accessing arrays
Create an array with square brackets, then read a value by its key:
PHP define and access an array
<?php
$fruits = ["apple", "banana", "cherry"]; // indexed
$student = ["name" => "John Doe", "age" => 25]; // associative
echo $fruits[0] . "\n"; // apple (first element, index 0)
echo $student["name"] . "\n"; // John DoeOutput:
apple
John DoeNote that indexed arrays are zero-based, so $fruits[0] is the first element.
Iterating an array with foreach
foreach is the idiomatic way to walk an iterable. For an indexed array you usually want just the value; for an associative array you typically want both key and value:
PHP iterate over arrays
<?php
$fruits = ["apple", "banana", "cherry"];
$student = ["name" => "John Doe", "age" => 25];
foreach ($fruits as $fruit) {
echo $fruit . "\n";
}
foreach ($student as $key => $value) {
echo "$key: $value\n";
}Output:
apple
banana
cherry
name: John Doe
age: 25Handy array functions
PHP ships dozens of array functions. A few you will reach for constantly:
array_keys($arr)— returns all keys as a new array.array_values($arr)— returns all values, re-indexed from0.count($arr)— returns the number of elements.sort($arr)— sorts values ascending in place, returningtrueon success (it does not return the sorted array).in_array($needle, $arr)—trueif the value exists.
PHP array functions in action
<?php
$scores = [40, 10, 30];
echo count($scores) . "\n"; // 3
print_r(array_keys($scores)); // [0, 1, 2]
sort($scores); // modifies $scores in place
print_r($scores); // [10, 30, 40]Output:
3
Array
(
[0] => 0
[1] => 1
[2] => 2
)
Array
(
[0] => 10
[1] => 30
[2] => 40
)The iterable pseudo-type
iterable is not a class — it is a type hint that means "array or Traversable". Use it on a parameter or return type when your function only needs to loop, and you do not want to force callers to convert their data to a plain array first.
PHP iterable type hint
<?php
function sumAll(iterable $numbers): int
{
$total = 0;
foreach ($numbers as $n) {
$total += $n;
}
return $total;
}
echo sumAll([1, 2, 3]) . "\n"; // works with an array
function countToThree(): iterable { // a generator is also iterable
yield 1;
yield 2;
yield 3;
}
echo sumAll(countToThree()) . "\n"; // works with a Traversable tooOutput:
6
6The payoff: sumAll() accepts a regular array and a lazily-generated stream without any extra code. See PHP Functions for more on type hints.
Generators: lazy iterables
A generator is a function that uses yield instead of return. It produces values one at a time, only when the loop asks for the next one, so it never builds the whole collection in memory. This is ideal for large or infinite sequences.
PHP generator example
<?php
function range_lazy(int $start, int $end): iterable
{
for ($i = $start; $i <= $end; $i++) {
yield $i; // pauses here and resumes on the next iteration
}
}
foreach (range_lazy(1, 5) as $value) {
echo $value . " ";
}
echo "\n";Output:
1 2 3 4 5Because nothing is stored, range_lazy(1, 1_000_000) uses the same tiny amount of memory as range_lazy(1, 5).
Custom iterable objects with Iterator
When you want full control over how an object is traversed, implement the Iterator interface. It requires five methods that foreach calls behind the scenes: rewind(), valid(), current(), key(), and next().
PHP custom Iterator
<?php
class EvenNumbers implements Iterator
{
private int $position = 0;
public function __construct(private array $items) {}
public function rewind(): void { $this->position = 0; }
public function valid(): bool { return isset($this->items[$this->position]); }
public function current(): mixed { return $this->items[$this->position]; }
public function key(): mixed { return $this->position; }
public function next(): void { $this->position++; }
}
$evens = new EvenNumbers([2, 4, 6]);
foreach ($evens as $n) {
echo $n . " ";
}
echo "\n";Output:
2 4 6Most of the time a generator is simpler than a full Iterator class — reach for Iterator only when you need custom rewind/key behaviour or want to expose iteration as part of an object's public API.
Checking whether a value is iterable
Use is_iterable() to test at runtime whether a value can be passed to foreach:
PHP is_iterable check
<?php
var_dump(is_iterable([1, 2, 3])); // bool(true)
var_dump(is_iterable("a string")); // bool(false)
var_dump(is_iterable((function () { yield 1; })())); // bool(true)Output:
bool(true)
bool(false)
bool(true)Conclusion
"Iterable" in PHP simply means loopable with foreach — and that covers arrays, Iterator/IteratorAggregate objects, and generators alike. Use plain arrays for ordinary collections, the iterable type hint to write functions that accept any of them, and generators when memory matters or the sequence is large. With these tools you can model data efficiently and keep your APIs flexible.