Eine Generator Funktion sieht genau so aus wie eine normale Funktion mit Ausnahme, dass nicht ein Wert zurückgeliefert wird, sondern ein Generator liefert so viele Werte zurück, wie nötig sind (Stichwort: yield).
Wenn eine Generator Funktion aufgerufen wird, wird ein Objekt zurück geliefert. Wenn Sie über dieses Objekt iterieren (zum Beispiel, via einer foreach Schleife), wird PHP die Generator Funktion so oft aufrufen, wie Werte benötigt werden, dann wird der Status des Generators gesichert, so dass fortgefahren werden kann, wenn der nächste Wert benötigt wird.
Sobald keine weiteren Werte zurückgeliefert werden können, kann die Generator Funktion einfach beendet werden, und der rufende Code wird fortgesetzt als gäbe es keine weiteren Werte in einem Array.
Hinweis:
Ein Generator kann keine Werte zurückliefern: macht man dies, wird ein Kompilierungs Fehler zurückgeliefert. Eine leere return Anweisung ist eine gültige Syntax innerhalb eines Generators und wird den Generator beenden.
Das Herz einer Generator Funktion ist das yield Schlüsselwort. In seiner einfachsten Form sieht das yield Schlüsselwort wie eine return Anweisung aus, ausser dass die Ausführung mit der Rückgabe nicht beendet wird, sondern yield vielmehr einen Wert für den Code bereitstellt über den der Generator schleift, und solange die Generator Funktion pausiert.
Beispiel #1 Ein einfaches Beispiel zum produzieren (yielding) von Werten
<?php
function generiere_eins_bis_drei() {
for ($i = 1; $i <= 3; $i++) {
// Hinweis: $i bleibt zwischen den yields erhalten.
yield $i;
}
}
$generator = generiere_eins_bis_drei();
foreach ($generator as $wert) {
echo "$wert\n";
}
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
1 2 3
Hinweis:
Intern werden sequentielle integer Schlüssel mit den produzieren Werten verknüpft, so wie mit einem nicht-assoziativem array.
Wenn Sie yield in einem Anweisungs Kontext nutzen (beispielsweise auf der rechten Seite einer Zuweisung), dann müssen Sie die yield Anweisung innerhalb von Klammern schreiben. Beispielsweise ist folgender Befehl gültig:
$daten = (yield $wert);
und diese Beispiel ist nicht gültig, und wird mit einen parse Fehler beendet:
$daten = yield $wert;
Diese Syntax wird in logischen UND-Funktionen bei der Generator::send() Methode genutzt.
PHP unterstützt ebenfalls assoziative Arrays, und Generatoren unterscheiden sich nicht davon. Als Ergänzung einfacher produzierter Werte, wie oben gezeigt, können Sie zur gleichen Zeit auch einen Schlüssel zurückliefern.
Die Syntax für das produzieren eines Schlüssel/Wert Paares ist sehr ähnlich wie die Definition von assoziativen Arrays. Siehe unten.
Beispiel #2 Produzieren eines Schlüssel/Wert Paares
<?php
/*
* Die Eingabe sind Semikolon getrennte Felder, mit dem ersten Feld
* welches als ID und Schlüssel genutzt wird.
*/
$eingabe = <<<'EOF'
1;PHP;mag Dollar Zeichen
2;Python;mag Leerzeichen
3;Ruby;mag Blöcke
EOF;
function eingabe_parser($eingabe) {
foreach (explode("\n", $eingabe) as $zeile) {
$felder = explode(';', $zeile);
$id = array_shift($felder);
yield $id => $felder;
}
}
foreach (eingabe_parser($eingabe) as $id => $felder) {
echo "$id:\n";
echo " $felder[0]\n";
echo " $felder[1]\n";
}
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
1: PHP mag Dollar Zeichen 2: Python mag Leerzeichen 3: Ruby mag Blöcke
Wie oben gezeigt mit dem zurückliefern einfacher Werte, muss man beim produzieren eines Schlüssel/Wert Paares im Zuweisungs Kontext den yield Befehl einklammern:
$daten = (yield $schluessel => $wert);
Yield kann ohne ein Argument aufgerufen werden, um ein NULL
Wert mit
einem automatischen Schlüssel zurückzuliefern.
Beispiel #3 Produzieren von NULL
s
<?php
function generiere_drei_nulls() {
foreach (range(1, 3) as $i) {
yield;
}
}
var_dump(iterator_to_array(generiere_drei_nulls()));
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
array(3) { [0]=> NULL [1]=> NULL [2]=> NULL }
Generator Funktionen sind genauso in der Lage Werte durch Referenzen zurückzuliefern wie durch Werte. Dies kann in gleicher weise erfolgen wie zurückliefern von Referenzen aus Funktionen: dies geschieht durch voranstellen eines kaufmännisches Unds zum Funktionsnamen.
Beispiel #4 Produzieren von Werten durch Referenzen
<?php
function &generiere_referenz() {
$wert = 3;
while ($wert > 0) {
yield $wert;
}
}
/*
* Hinweis: wir können $nummer innerhalb der Schleife ändern, und
* weil der Generator Referenzen zurückliefert, wird $wert
* innerhalb von generiere_referenz() verändert.
*/
foreach (generiere_referenz() as &$nummer) {
echo (--$nummer).'... ';
}
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
2... 1... 0...