In PHP, an iterable is a type that can be traversed using a foreach loop. Iterables are a versatile feature that allows functions, methods, and variables to accept any kind of traversable data, such as arrays or objects implementing the Traversable interface. Introduced in PHP 7.1, the iterable type provides type safety while maintaining flexibility, enabling developers to write robust, reusable, and clean code.
Iterables are especially useful in modern PHP applications, where large datasets, collections, or external libraries return objects instead of arrays. By using iterables, your code can handle both arrays and objects consistently, without depending on a specific data type.
What is an Iterable?
An iterable is any value that can be looped over with foreach. This includes:
-
Arrays – the simplest iterable.
-
Objects implementing Traversable, which include classes implementing Iterator or IteratorAggregate.
Using iterable in function parameters or return types ensures only traversable values are accepted, reducing errors caused by passing incompatible types.
Declaring Iterable Parameters
You can declare a function to accept any iterable:
function printItems(iterable $items) {
foreach ($items as $item) {
echo $item . "<br>";
}
}
// Using an array
$array = [1, 2, 3];
printItems($array);
// Using an object implementing Traversable
$set = new ArrayIterator(["A", "B", "C"]);
printItems($set);
This approach allows a single function to work with multiple types of traversable data.
Iterables with Arrays
Arrays are the most common iterables:
$numbers = [10, 20, 30];
foreach ($numbers as $num) {
echo $num . "<br>";
}
When a function accepts an iterable, it works natively with arrays, making it compatible with most existing PHP code.
Iterables with Objects
Objects can also be iterable if they implement Iterator or IteratorAggregate:
class MyCollection implements IteratorAggregate {
private $items = [];
public function __construct(array $items) {
$this->items = $items;
}
public function getIterator(): Traversable {
return new ArrayIterator($this->items);
}
}
$collection = new MyCollection([100, 200, 300]);
foreach ($collection as $value) {
echo $value . "<br>";
}
Here, MyCollection implements IteratorAggregate, which returns a Traversable object. This makes the object fully compatible with iterable type hints.
Returning Iterables from Functions
Functions can return iterables instead of arrays, improving flexibility and scalability:
function getItems(): iterable {
return ["apple", "banana", "cherry"];
}
foreach (getItems() as $item) {
echo $item . "<br>";
}
This ensures the function always returns traversable data, whether it is an array or an object implementing Traversable.
Using Generators as Iterables
Generators are a powerful way to create lazy iterables, allowing you to handle large datasets efficiently:
function numberGenerator(int $max): iterable {
for ($i = 1; $i <= $max; $i++) {
yield $i;
}
}
foreach (numberGenerator(5) as $num) {
echo $num . "<br>";
}
Generators combined with iterables allow processing data streams or large files without consuming large amounts of memory.
Combining Iterables and Type Safety
The iterable type ensures type safety while allowing flexibility:
function sumValues(iterable $values): int {
$sum = 0;
foreach ($values as $val) {
$sum += $val;
}
return $sum;
}
echo sumValues([1, 2, 3]); // 6
echo sumValues(new ArrayIterator([4, 5, 6])); // 15
This prevents errors like passing a string or integer to a function expecting a traversable value.
Real-World Use Cases
-
Database Results: Returning iterables from database queries using PDOStatement or Generator.
-
Collections: Custom collection classes that implement IteratorAggregate for uniform iteration.
-
File Processing: Iterating over lines in a file using generators.
-
API Data Streams: Handling large API responses efficiently with iterable objects.
Example – iterating database rows lazily:
function fetchUsers(PDO $pdo): iterable {
$stmt = $pdo->query("SELECT name FROM users");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
yield $row;
}
}
Best Practices
-
Use iterable type hints when a function can accept arrays or traversable objects.
-
Avoid assuming the iterable is an array; use foreach instead of array functions.
-
Use generators for memory-efficient iteration over large datasets.
-
Implement IteratorAggregate in custom classes to make them iterable.
-
Declare return type iterable for functions returning traversable data.
Common Mistakes
-
Passing non-traversable types to an iterable parameter.
-
Using array-specific functions like array_merge() on generic iterables.
-
Forgetting to implement Iterator or IteratorAggregate for custom iterable objects.
-
Returning a non-iterable value when the function specifies iterable return type.
Summary of the Tutorial
-
Iterables are any values that can be traversed with foreach, including arrays and objects implementing Traversable.
-
The iterable type hint allows functions and methods to accept multiple data types safely and flexibly.
-
Generators provide lazy evaluation, allowing large datasets to be processed efficiently.
-
Iterables make PHP code more modular, maintainable, and compatible with different data structures.
-
Using iterables properly ensures your functions are robust, type-safe, and future-proof.
Mastering iterables allows developers to write flexible, memory-efficient PHP code that can handle arrays, generators, and custom traversable objects seamlessly.