is_iterable()
Die Funktion is_iterable() prüft ab PHP 7.1, ob ein Wert iterierbar ist – also ein Array oder ein Traversable-Objekt darstellt.
Einführung
is_iterable() ist eine eingebaute PHP-Funktion (verfügbar seit PHP 7.1), die angibt, ob ein Wert mit einer foreach-Schleife durchlaufen werden kann. Sie gibt true für genau zwei Arten von Werten zurück:
- Arrays — jedes Array ist iterierbar.
- Objekte, die das
Traversable-Interface implementieren — in der Praxis sind das Objekte, dieIteratoroderIteratorAggregateimplementieren, sowie Generatoren (Funktionen, dieyieldverwenden).
Alles andere — Strings, Integer, Booleans, null und einfache Objekte (wie stdClass) — ist nicht iterierbar, auch wenn es intuitiv „listenähnlich" wirkt. Diese Seite behandelt die Syntax, was als iterierbar gilt, die häufigsten Fallstricke und wann der Einsatz von is_iterable() tatsächlich sinnvoll ist.
Syntax
is_iterable(mixed $value): boolDie Funktion nimmt ein einziges Argument, $value, und gibt einen boolean zurück:
| Argument | Ergebnis |
|---|---|
| Ein Array | true |
Ein Traversable-Objekt (Iterator, IteratorAggregate, Generator) | true |
Alles andere (string, int, einfaches Objekt, null, …) | false |
Seit PHP 8.0 gibt es außerdem einen passenden Pseudo-Typ, iterable, der als Typdeklaration verwendet werden kann — siehe Wann man ihn einsetzt weiter unten.
Grundlegendes Beispiel
$var1 ist ein Array, also ist es iterierbar. $var2 ist ein String — obwohl man zeichenweise auf einen String zugreifen kann, lässt er sich nicht mit foreach durchlaufen, weshalb is_iterable() false zurückgibt.
Was als iterierbar gilt
Die interessanten Fälle sind Objekte. Ein Objekt ist nur iterierbar, wenn es Traversable implementiert (direkt oder über Iterator/IteratorAggregate), oder wenn es ein Generator ist. Ein einfaches Objekt ist es nicht.
<?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
?>Die wichtigste Erkenntnis: Ein stdClass (oder ein beliebiges Objekt ohne Traversable) gibt false zurück, obwohl foreach tatsächlich über seine öffentlichen Eigenschaften iterieren kann. is_iterable() meldet absichtlich nur Werte, die vertragsgemäß iterierbar sind, nicht solche, die es zufällig sind.
Häufige Fallstricke
- Strings sind nicht iterierbar. Ein String ist ein skalarer Wert, keine Kollektion, daher ist
is_iterable("abc")false. Um auf einen String zu prüfen, verwende stattdessenis_string(). - Einfache Objekte schlagen fehl.
is_iterable(new stdClass())istfalse. Wenn man nur wissen möchte, ob ein Wert irgendein Objekt ist, verwendet manis_object(); wenn man speziell ein durchlaufbares Objekt benötigt, istis_iterable()die richtige Wahl. - Es ist nicht dasselbe wie
is_array().is_array()isttruenur für Arrays und lehnt Generatoren undTraversable-Objekte ab. Verwendeis_iterable(), wenn du sowohl Arrays als auch Iterator-Objekte akzeptieren möchtest. nullgibtfalsezurück. Das Übergeben eines nicht initialisierten odernull-Werts ist sicher — es wird einfachfalsezurückgegeben, ohne einen Fehler auszulösen.
Wann man es einsetzt
Verwende is_iterable() als Guard-Clause vor einem foreach, damit eine Funktion sowohl ein Array als auch einen lazy Iterator akzeptieren kann, ohne bei fehlerhafter Eingabe abzustürzen:
<?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
?>Dieselbe Funktion verarbeitet sowohl ein einfaches Array als auch einen Generator, da beide is_iterable() erfüllen.
Oft ist die sauberere Wahl die iterable-Typdeklaration (PHP 7.1+), mit der PHP die Einschränkung für dich durchsetzt, sodass die manuelle Prüfung vollständig entfällt:
<?php
function sumAll(iterable $data): int {
$total = 0;
foreach ($data as $value) {
$total += $value;
}
return $total;
}
?>Greife auf die is_iterable()-Funktion zurück, wenn der Wert mixed ist und du zur Laufzeit verzweigen möchtest; greife auf den iterable-Type Hint zurück, wenn Iterierbarkeit eine harte Anforderung des Parameters ist.
Fazit
is_iterable() beantwortet eine präzise Frage: Kann dieser Wert von einer foreach-Schleife durchlaufen werden? Es gibt true für Arrays und Traversable-Objekte (einschließlich Generatoren) und false für alles andere zurück. Verwende es als Laufzeit-Guard für mixed-Eingaben, bevorzuge den iterable-Type Hint, wenn Iterierbarkeit zwingend erforderlich ist, und denke daran, dass es strenger ist als es aussieht — Strings und einfache Objekte sind nicht iterierbar. Für verwandte Prüfungen siehe is_array(), is_object() und gettype().