PHP Iterables
PHP Iterables sind Datenstrukturen wie Arrays und Traversable-Objekte, die mit foreach durchlaufen werden können. Alles über Typen und Generatoren.
Einführung in PHP Iterables
In PHP ist ein Iterable alles, was sich mit foreach durchlaufen lässt. Dazu gehören zwei Arten von Werten:
- Arrays — die alltägliche Datenstruktur, die eine geordnete Sammlung von Schlüssel/Wert-Paaren enthält.
Traversable-Objekte — Objekte, die PHP durchlaufen kann, weil sie das eingebauteTraversable-Interface implementieren (in der Praxis überIteratoroderIteratorAggregate, oder als Generator).
PHP 7.1 hat den iterable-Pseudo-Typ eingeführt, damit man deklarieren kann „gib mir alles, worüber ich mit foreach iterieren kann", ohne sich darum zu kümmern, ob der Aufrufer ein Array oder ein Objekt übergibt. Diese Seite erklärt, was als Iterable gilt, wie man die einzelnen Arten erstellt und durchläuft und wann man zu den Lazy Iterables greift, die Generatoren bieten.
Dieses Kapitel baut auf PHP Arrays und der foreach-Schleife auf. Falls du mit einem der beiden noch nicht vertraut bist, lies diese zuerst.
Arrays: das gebräuchlichste Iterable
Arrays gibt es in zwei Varianten, und der einzige Unterschied liegt im Typ des verwendeten Schlüssels:
- Ein indiziertes Array speichert Werte unter automatisch vergebenen Integer-Schlüsseln, beginnend bei
0. Siehe Indexed Arrays. - Ein assoziatives Array verwendet Strings (oder selbst gewählte Integer) als Schlüssel. Siehe Associative Arrays.
Ein einzelnes Array kann beide Stile mischen, und die Werte können jeden Datentyp haben.
Arrays erstellen und darauf zugreifen
Ein Array wird mit eckigen Klammern erstellt, und auf einen Wert greift man über seinen Schlüssel zu:
PHP Array definieren und darauf zugreifen
<?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 DoeAusgabe:
apple
John DoeBeachte, dass indizierte Arrays nullbasiert sind, d. h. $fruits[0] ist das erste Element.
Mit foreach über ein Array iterieren
foreach ist die idiomatische Methode, um ein Iterable zu durchlaufen. Bei einem indizierten Array benötigt man in der Regel nur den Wert; bei einem assoziativen Array braucht man typischerweise sowohl Schlüssel als auch Wert:
PHP über Arrays iterieren
<?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";
}Ausgabe:
apple
banana
cherry
name: John Doe
age: 25Hilfreiche Array-Funktionen
PHP bietet Dutzende von Array-Funktionen. Ein paar davon werden ständig gebraucht:
array_keys($arr)— gibt alle Schlüssel als neues Array zurück.array_values($arr)— gibt alle Werte zurück, neu indiziert ab0.count($arr)— gibt die Anzahl der Elemente zurück.sort($arr)— sortiert die Werte aufsteigend in place und gibt bei Erfolgtruezurück (nicht das sortierte Array).in_array($needle, $arr)—true, wenn der Wert vorhanden ist.
PHP Array-Funktionen in Aktion
<?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]Ausgabe:
3
Array
(
[0] => 0
[1] => 1
[2] => 2
)
Array
(
[0] => 10
[1] => 30
[2] => 40
)Der iterable-Pseudo-Typ
iterable ist keine Klasse — es ist ein Typ-Hinweis, der bedeutet „Array oder Traversable". Verwende ihn als Parameter- oder Rückgabetyp, wenn eine Funktion nur über Daten iterieren muss und man Aufrufer nicht zwingen will, ihre Daten zuerst in ein einfaches Array umzuwandeln.
PHP iterable-Typ-Hinweis
<?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 tooAusgabe:
6
6Der Vorteil: sumAll() akzeptiert ein gewöhnliches Array und einen lazy generierten Stream ohne zusätzlichen Code. Mehr zu Typ-Hinweisen findest du unter PHP Functions.
Generatoren: Lazy Iterables
Ein Generator ist eine Funktion, die yield anstelle von return verwendet. Sie liefert Werte einen nach dem anderen, nur wenn die Schleife den nächsten anfordert, und baut daher niemals die gesamte Kollektion im Speicher auf. Das ist ideal für große oder unendliche Sequenzen.
PHP Generator-Beispiel
<?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";Ausgabe:
1 2 3 4 5Da nichts gespeichert wird, benötigt range_lazy(1, 1_000_000) genauso wenig Speicher wie range_lazy(1, 5).
Benutzerdefinierte Iterable-Objekte mit Iterator
Wenn man volle Kontrolle darüber haben möchte, wie ein Objekt durchlaufen wird, implementiert man das Iterator-Interface. Es erfordert fünf Methoden, die foreach im Hintergrund aufruft: rewind(), valid(), current(), key() und next().
PHP benutzerdefinierter 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";Ausgabe:
2 4 6Meistens ist ein Generator einfacher als eine vollständige Iterator-Klasse — greife zu Iterator nur dann, wenn du benutzerdefiniertes Rewind/Key-Verhalten benötigst oder die Iteration als Teil der öffentlichen API eines Objekts bereitstellen möchtest.
Prüfen, ob ein Wert iterable ist
Verwende is_iterable(), um zur Laufzeit zu prüfen, ob ein Wert an foreach übergeben werden kann:
PHP is_iterable-Prüfung
<?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)Ausgabe:
bool(true)
bool(false)
bool(true)Fazit
„Iterable" in PHP bedeutet schlicht mit foreach durchlaufbar — und das umfasst Arrays, Iterator/IteratorAggregate-Objekte und Generatoren gleichermaßen. Verwende einfache Arrays für gewöhnliche Sammlungen, den iterable-Typ-Hinweis, um Funktionen zu schreiben, die jeden dieser Typen akzeptieren, und Generatoren, wenn Speicher eine Rolle spielt oder die Sequenz groß ist. Mit diesen Werkzeugen kannst du Daten effizient modellieren und deine APIs flexibel halten.