Heim > Artikel > Backend-Entwicklung > Neue Funktionen von Generatoren in PHP7: Generator-Delegat (yield-from) & Rückgabewert (return-value)
Dieser Artikel stellt Ihnen die neuen Funktionen von Generatoren in PHP7 vor: Generatordelegation (Ertrag) und Rückgabewert (Return-Value). Ich hoffe, er hilft Ihnen Du.
Generator-Delegierter
Übersetzen Sie einfach die Beschreibung der offiziellen Dokumentation:
In PHP7 werden über den Generator-Delegaten (Ertrag von) andere Generatoren, iterierbare Objekte und Arrays werden an äußere Generatoren delegiert. Der äußere Generator liefert zunächst sequentiell den delegierten Wert und dann weiterhin den in ihm selbst definierten Wert.
Die Verwendung von yield from kann es uns erleichtern, klarere Generatorverschachtelungen zu schreiben, und Codeverschachtelungsaufrufe sind zum Schreiben komplexer Systeme erforderlich.
Das obige Beispiel:
<?php function echoTimes($msg, $max) { for ($i = 1; $i <= $max; ++$i) { echo "$msg iteration $i\n"; yield; } } function task() { yield from echoTimes('foo', 10); // print foo ten times echo "---\n"; yield from echoTimes('bar', 5); // print bar five times } foreach (task() as $item) { ; }
Das Obige gibt Folgendes aus:
foo iteration 1 foo iteration 2 foo iteration 3 foo iteration 4 foo iteration 5 foo iteration 6 foo iteration 7 foo iteration 8 foo iteration 9 foo iteration 10 --- bar iteration 1 bar iteration 2 bar iteration 3 bar iteration 4 bar iteration 5
Natürlich kann der interne Generator auch von seinem übergeordneten Generator gesendete Informationen oder Ausnahmen akzeptieren, da yield from ein übergeordneter Generator ist. Untergeordneter Generator Erstellen Sie einen Zwei-Wege-Kanal. Hier ist ohne weiteres ein Beispiel:
<?php function echoMsg($msg) { while (true) { $i = yield; if($i === null){ break; } if(!is_numeric($i)){ throw new Exception("Hoo! must give me a number"); } echo "$msg iteration $i\n"; } } function task2() { yield from echoMsg('foo'); echo "---\n"; yield from echoMsg('bar'); } $gen = task2(); foreach (range(1,10) as $num) { $gen->send($num); } $gen->send(null); foreach (range(1,5) as $num) { $gen->send($num); } //$gen->send("hello world"); //try it ,gay
Die Ausgabe ist die gleiche wie im vorherigen Beispiel.
Generator-Rückgabewert
Wenn der Generator iteriert wird oder zum Schlüsselwort „return“ läuft, wird ein Wert an den Generator zurückgegeben.
Es gibt zwei Möglichkeiten, diesen Rückgabewert zu erhalten:
Verwenden Sie die Methode $ret = Generator::getReturn().
Verwenden Sie den Ausdruck $ret = yield from Generator().
Das obige Beispiel:
<?php function echoTimes($msg, $max) { for ($i = 1; $i <= $max; ++$i) { echo "$msg iteration $i\n"; yield; } return "$msg the end value : $i\n"; } function task() { $end = yield from echoTimes('foo', 10); echo $end; $gen = echoTimes('bar', 5); yield from $gen; echo $gen->getReturn(); } foreach (task() as $item) { ; }
Das Ausgabeergebnis wird nicht veröffentlicht, jeder muss es erraten haben.
Sie können sehen, dass die Kombination von yield from und return das Schreiben von yield eher dem synchronen Moduscode ähnelt, den wir normalerweise schreiben. Schließlich ist dies einer der Gründe, warum PHP über die Generatorfunktion verfügt.
Ein nicht blockierender Webserver
Jetzt nutzen wir diese beiden neuen Funktionen in PHP7, um diesen Webserver neu zu schreiben, der nur mehr als 100 Zeilen Code benötigt.
Der Code lautet wie folgt:
<?php class CoSocket { protected $masterCoSocket = null; public $socket; protected $handleCallback; public $streamPoolRead = []; public $streamPoolWrite = []; public function __construct($socket, CoSocket $master = null) { $this->socket = $socket; $this->masterCoSocket = $master ?? $this; } public function accept() { $isSelect = yield from $this->onRead(); $acceptS = null; if ($isSelect && $as = stream_socket_accept($this->socket, 0)) { $acceptS = new CoSocket($as, $this); } return $acceptS; } public function read($size) { yield from $this->onRead(); yield ($data = fread($this->socket, $size)); return $data; } public function write($string) { yield from $this->onWriter(); yield fwrite($this->socket, $string); } public function close() { unset($this->masterCoSocket->streamPoolRead[(int)$this->socket]); unset($this->masterCoSocket->streamPoolWrite[(int)$this->socket]); yield ($success = @fclose($this->socket)); return $success; } public function onRead($timeout = null) { $this->masterCoSocket->streamPoolRead[(int)$this->socket] = $this->socket; $pool = $this->masterCoSocket->streamPoolRead; $rSocks = []; $wSocks = $eSocks = null; foreach ($pool as $item) { $rSocks[] = $item; } yield ($num = stream_select($rSocks, $wSocks, $eSocks, $timeout)); return $num; } public function onWriter($timeout = null) { $this->masterCoSocket->streamPoolWrite[(int)$this->socket] = $this->socket; $pool = $this->masterCoSocket->streamPoolRead; $wSocks = []; $rSocks = $eSocks = null; foreach ($pool as $item) { $wSocks[] = $item; } yield ($num = stream_select($rSocks, $wSocks, $eSocks, $timeout)); return $num; } public function onRequest() { /** @var self $socket */ $socket = yield from $this->accept(); if (empty($socket)) { return false; } $data = yield from $socket->read(8192); $response = call_user_func($this->handleCallback, $data); yield from $socket->write($response); return yield from $socket->close(); } public static function start($port, callable $callback) { echo "Starting server at port $port...\n"; $socket = @stream_socket_server("tcp://0.0.0.0:$port", $errNo, $errStr); if (!$socket) throw new Exception($errStr, $errNo); stream_set_blocking($socket, 0); $coSocket = new self($socket); $coSocket->handleCallback = $callback; function gen($coSocket) { /** @var self $coSocket */ while (true) yield from $coSocket->onRequest(); } foreach (gen($coSocket) as $item){}; } } CoSocket::start(8000, function ($data) { $response = <<<RES HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 12 Connection: close hello world! RES; return $response; });
Empfohlene verwandte Artikel:
Einfache Analyse von PHP-Generatoren
Das obige ist der detaillierte Inhalt vonNeue Funktionen von Generatoren in PHP7: Generator-Delegat (yield-from) & Rückgabewert (return-value). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!