Signatur
Beschreibung
ClosedGeneratorException ist eine spezialisierte Laufzeit-Ausnahme, die PHP intern wirft, wenn auf einen Generator zugegriffen wird, der sich bereits im geschlossenen Zustand befindet. Ein Generator gilt als geschlossen, sobald er vollständig durchgelaufen ist, explizit mit Generator::getReturn() oder durch Garbage Collection beendet wurde oder wenn er delegiert war (yield from) und der delegierte Generator ebenfalls abgeschlossen ist.
Typischerweise tritt diese Ausnahme auf, wenn Generator::current(), Generator::send() oder Generator::throw() nach dem Ende des Generators aufgerufen werden, ohne vorher per Generator::valid() zu prüfen, ob der Generator noch aktiv ist. Sie erbt direkt von RuntimeException und kann daher mit einem regulären catch (RuntimeException $e)-Block abgefangen werden.
Um diese Ausnahme zu vermeiden, sollte man vor jedem Zugriff auf einen Generator dessen Zustand mit Generator::valid() prüfen oder den Zugriff in einen try/catch-Block kapseln. Besonders in delegierten Generatoren (yield from) und bei der Nutzung von Generator::getReturn() ist Vorsicht geboten, da letztere Methode selbst eine ClosedGeneratorException auslösen kann, wenn der Generator noch nicht abgeschlossen ist.
Beispiele
ClosedGeneratorException beim Zugriff auf geschlossenen Generator
<?php
function meinGenerator(): Generator {
yield 1;
yield 2;
}
$gen = meinGenerator();
// Generator vollständig durchlaufen
foreach ($gen as $value) {
echo $value . PHP_EOL;
}
// Generator ist nun geschlossen — Zugriff löst Ausnahme aus
try {
$gen->send(42);
} catch (ClosedGeneratorException $e) {
echo 'Fehler: ' . $e->getMessage() . PHP_EOL;
}
Sicherer Zugriff mit valid()-Prüfung
<?php
function zaehler(int $bis): Generator {
for ($i = 1; $i <= $bis; $i++) {
yield $i;
}
}
$gen = zaehler(3);
while ($gen->valid()) {
echo $gen->current() . PHP_EOL;
$gen->next();
}
// Kein Zugriff mehr, daher keine ClosedGeneratorException
echo 'Generator sauber beendet.' . PHP_EOL;
// Rückgabewert nach ordnungsgemäßem Abschluss abrufen
try {
$rueckgabe = $gen->getReturn();
echo 'Rückgabewert: ' . var_export($rueckgabe, true) . PHP_EOL;
} catch (ClosedGeneratorException $e) {
echo 'Kein Rückgabewert verfügbar: ' . $e->getMessage() . PHP_EOL;
}
// Wichtig · Fallstricke
Fallstrick: Generator::getReturn() wirft eine ClosedGeneratorException, wenn der Generator noch nicht abgeschlossen ist — also genau das Gegenteil der üblichen Fälle. Die Methode darf ausschließlich aufgerufen werden, wenn Generator::valid() false zurückgibt.
Da ClosedGeneratorException von RuntimeException erbt, wird sie auch von allgemeineren catch-Blöcken für RuntimeException oder Exception erfasst. Für eine präzise Fehlerbehandlung empfiehlt sich die explizite Verwendung von catch (ClosedGeneratorException $e).