<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Generator syntax</title> </head> <body><div class="manualnavbar" style="text-align: center;"> <div class="prev" style="text-align: left; float: left;"><a href="language.generators.overview.html">Generators overview</a></div> <div class="next" style="text-align: right; float: right;"><a href="language.generators.comparison.html">Comparing generators with Iterator objects</a></div> <div class="up"><a href="language.generators.html">Generators</a></div> <div class="home"><a href="index.html">PHP Manual</a></div> </div><hr /><div id="language.generators.syntax" class="sect1"> <h2 class="title">Generator syntax</h2> <p class="para"> A generator function looks just like a normal function, except that instead of returning a value, a generator <a href="language.generators.syntax.html#control-structures.yield" class="link">yield</a>s as many values as it needs to. </p> <p class="para"> When a generator function is called, it returns an object that can be iterated over. When you iterate over that object (for instance, via a <a href="control-structures.foreach.html" class="link">foreach</a> loop), PHP will call the object's iteration methods each time it needs a value, then saves the state of the generator when the generator yields a value so that it can be resumed when the next value is required. </p> <p class="para"> Once there are no more values to be yielded, then the generator can simply exit, and the calling code continues just as if an array has run out of values. </p> <blockquote class="note"><p><strong class="note">Note</strong>: <p class="para"> In PHP 5, a generator could not return a value: doing so would result in a compile error. An empty <strong class="command">return</strong> statement was valid syntax within a generator and it would terminate the generator. Since PHP 7.0, a generator can return values, which can be retrieved using <span class="methodname"><a href="generator.getreturn.html" class="methodname">Generator::getReturn()</a></span>. </p> </p></blockquote> <div class="sect2" id="control-structures.yield"> <h3 class="title"><strong class="command">yield</strong> keyword</h3> <p class="para"> The heart of a generator function is the <strong class="command">yield</strong> keyword. In its simplest form, a yield statement looks much like a return statement, except that instead of stopping execution of the function and returning, yield instead provides a value to the code looping over the generator and pauses execution of the generator function. </p> <div class="example" id="example-285"> <p><strong>Example #1 A simple example of yielding values</strong></p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">gen_one_to_three</span><span style="color: #007700">() {<br /> for (</span><span style="color: #0000BB">$i </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">; </span><span style="color: #0000BB">$i </span><span style="color: #007700"><= </span><span style="color: #0000BB">3</span><span style="color: #007700">; </span><span style="color: #0000BB">$i</span><span style="color: #007700">++) {<br /> </span><span style="color: #FF8000">// Note that $i is preserved between yields.<br /> </span><span style="color: #0000BB">yield $i</span><span style="color: #007700">;<br /> }<br />}<br /><br /></span><span style="color: #0000BB">$generator </span><span style="color: #007700">= </span><span style="color: #0000BB">gen_one_to_three</span><span style="color: #007700">();<br />foreach (</span><span style="color: #0000BB">$generator </span><span style="color: #007700">as </span><span style="color: #0000BB">$value</span><span style="color: #007700">) {<br /> echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$value</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> <div class="example-contents"><p>The above example will output:</p></div> <div class="example-contents screen"> <div class="cdata"><pre> 1 2 3 </pre></div> </div> </div> <blockquote class="note"><p><strong class="note">Note</strong>: <p class="para"> Internally, sequential integer keys will be paired with the yielded values, just as with a non-associative array. </p> </p></blockquote> <div class="caution"><strong class="caution">Caution</strong> <p class="para"> If you use yield in an expression context (for example, on the right hand side of an assignment), you must surround the yield statement with parentheses in PHP 5. For example, this is valid: </p> <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> $data = (yield $value);</span> </code></div> </div> </div> <p class="para"> But this is not, and will result in a parse error in PHP 5: </p> <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> $data = yield $value;</span> </code></div> </div> </div> <p class="para"> The parenthetical restrictions do not apply in PHP 7. </p> <p class="para"> The value that will be assigned to <var class="varname"><var class="varname">$data</var></var> is the value passed to <span class="methodname"><a href="generator.send.html" class="methodname">Generator::send()</a></span>, or <strong><code>NULL</code></strong> if <span class="methodname"><a href="generator.next.html" class="methodname">Generator::next()</a></span> is called instead. </p> </div> <div class="sect3" id="control-structures.yield.associative"> <h4 class="title">Yielding values with keys</h4> <p class="para"> PHP also supports associative arrays, and generators are no different. In addition to yielding simple values, as shown above, you can also yield a key at the same time. </p> <p class="para"> The syntax for yielding a key/value pair is very similar to that used to define an associative array, as shown below. </p> <div class="example" id="example-286"> <p><strong>Example #2 Yielding a key/value pair</strong></p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000">/*<br /> * The input is semi-colon separated fields, with the first<br /> * field being an ID to use as a key.<br /> */<br /><br /></span><span style="color: #0000BB">$input </span><span style="color: #007700">= <<<'EOF'<br /></span><span style="color: #DD0000">1;PHP;Likes dollar signs<br />2;Python;Likes whitespace<br />3;Ruby;Likes blocks<br /></span><span style="color: #007700">EOF;<br /><br />function </span><span style="color: #0000BB">input_parser</span><span style="color: #007700">(</span><span style="color: #0000BB">$input</span><span style="color: #007700">) {<br /> foreach (</span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">, </span><span style="color: #0000BB">$input</span><span style="color: #007700">) as </span><span style="color: #0000BB">$line</span><span style="color: #007700">) {<br /> </span><span style="color: #0000BB">$fields </span><span style="color: #007700">= </span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #DD0000">';'</span><span style="color: #007700">, </span><span style="color: #0000BB">$line</span><span style="color: #007700">);<br /> </span><span style="color: #0000BB">$id </span><span style="color: #007700">= </span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$fields</span><span style="color: #007700">);<br /><br /> </span><span style="color: #0000BB">yield $id </span><span style="color: #007700">=> </span><span style="color: #0000BB">$fields</span><span style="color: #007700">;<br /> }<br />}<br /><br />foreach (</span><span style="color: #0000BB">input_parser</span><span style="color: #007700">(</span><span style="color: #0000BB">$input</span><span style="color: #007700">) as </span><span style="color: #0000BB">$id </span><span style="color: #007700">=> </span><span style="color: #0000BB">$fields</span><span style="color: #007700">) {<br /> echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$id</span><span style="color: #DD0000">:\n"</span><span style="color: #007700">;<br /> echo </span><span style="color: #DD0000">" </span><span style="color: #0000BB">$fields</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br /> echo </span><span style="color: #DD0000">" </span><span style="color: #0000BB">$fields</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> <div class="example-contents"><p>The above example will output:</p></div> <div class="example-contents screen"> <div class="cdata"><pre> 1: PHP Likes dollar signs 2: Python Likes whitespace 3: Ruby Likes blocks </pre></div> </div> </div> <div class="caution"><strong class="caution">Caution</strong> <p class="para"> As with the simple value yields shown earlier, yielding a key/value pair in an expression context requires the yield statement to be parenthesised: </p> <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> $data = (yield $key => $value);</span> </code></div> </div> </div> </div> </div> <div class="sect3" id="control-structures.yield.null"> <h4 class="title">Yielding null values</h4> <p class="para"> Yield can be called without an argument to yield a <strong><code>NULL</code></strong> value with an automatic key. </p> <div class="example" id="example-287"> <p><strong>Example #3 Yielding <strong><code>NULL</code></strong>s</strong></p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">gen_three_nulls</span><span style="color: #007700">() {<br /> foreach (</span><span style="color: #0000BB">range</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">3</span><span style="color: #007700">) as </span><span style="color: #0000BB">$i</span><span style="color: #007700">) {<br /> </span><span style="color: #0000BB">yield</span><span style="color: #007700">;<br /> }<br />}<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">iterator_to_array</span><span style="color: #007700">(</span><span style="color: #0000BB">gen_three_nulls</span><span style="color: #007700">()));<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> <div class="example-contents"><p>The above example will output:</p></div> <div class="example-contents screen"> <div class="cdata"><pre> array(3) { [0]=> NULL [1]=> NULL [2]=> NULL } </pre></div> </div> </div> </div> <div class="sect3" id="control-structures.yield.references"> <h4 class="title">Yielding by reference</h4> <p class="para"> Generator functions are able to yield values by reference as well as by value. This is done in the same way as <a href="functions.returning-values.html" class="link">returning references from functions</a>: by prepending an ampersand to the function name. </p> <div class="example" id="example-288"> <p><strong>Example #4 Yielding values by reference</strong></p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function &</span><span style="color: #0000BB">gen_reference</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">3</span><span style="color: #007700">;<br /><br /> while (</span><span style="color: #0000BB">$value </span><span style="color: #007700">> </span><span style="color: #0000BB">0</span><span style="color: #007700">) {<br /> </span><span style="color: #0000BB">yield $value</span><span style="color: #007700">;<br /> }<br />}<br /><br /></span><span style="color: #FF8000">/*<br /> * Note that we can change $number within the loop, and<br /> * because the generator is yielding references, $value<br /> * within gen_reference() changes.<br /> */<br /></span><span style="color: #007700">foreach (</span><span style="color: #0000BB">gen_reference</span><span style="color: #007700">() as &</span><span style="color: #0000BB">$number</span><span style="color: #007700">) {<br /> echo (--</span><span style="color: #0000BB">$number</span><span style="color: #007700">).</span><span style="color: #DD0000">'... '</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> <div class="example-contents"><p>The above example will output:</p></div> <div class="example-contents screen"> <div class="cdata"><pre> 2... 1... 0... </pre></div> </div> </div> </div> <div class="sect3" id="control-structures.yield.from"> <h4 class="title">Generator delegation via <strong class="command">yield from</strong></h4> <p class="para"> In PHP 7, generator delegation allows you to yield values from another generator, <a href="class.traversable.html" class="classname">Traversable</a> object, or <span class="type"><a href="language.types.array.html" class="type array">array</a></span> by using the <strong class="command">yield from</strong> keyword. The outer generator will then yield all values from the inner generator, object, or array until that is no longer valid, after which execution will continue in the outer generator. </p> <p class="para"> If a generator is used with <strong class="command">yield from</strong>, the <strong class="command">yield from</strong> expression will also return any value returned by the inner generator. </p> <div class="caution"><strong class="caution">Caution</strong> <h1 class="title">Storing into an array (e.g. with <span class="function"><a href="function.iterator-to-array.html" class="function">iterator_to_array()</a></span>)</h1> <p class="para"> <strong class="command">yield from</strong> does not reset the keys. It preserves the keys returned by the <a href="class.traversable.html" class="classname">Traversable</a> object, or <span class="type"><a href="language.types.array.html" class="type array">array</a></span>. Thus some values may share a common key with another <strong class="command">yield</strong> or <strong class="command">yield from</strong>, which, upon insertion into an array, will overwrite former values with that key. </p> <p class="para"> A common case where this matters is <span class="function"><a href="function.iterator-to-array.html" class="function">iterator_to_array()</a></span> returning a keyed array by default, leading to possibly unexpected results. <span class="function"><a href="function.iterator-to-array.html" class="function">iterator_to_array()</a></span> has a second parameter <code class="parameter">use_keys</code> which can be set to <strong><code>FALSE</code></strong> to collect all the values while ignoring the keys returned by the <a href="class.generator.html" class="classname">Generator</a>. </p> <div class="example" id="example-289"> <p><strong>Example #5 <strong class="command">yield from</strong> with <span class="function"><a href="function.iterator-to-array.html" class="function">iterator_to_array()</a></span></strong></p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">from</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 1</span><span style="color: #007700">; </span><span style="color: #FF8000">// key 0<br /> </span><span style="color: #0000BB">yield 2</span><span style="color: #007700">; </span><span style="color: #FF8000">// key 1<br /> </span><span style="color: #0000BB">yield 3</span><span style="color: #007700">; </span><span style="color: #FF8000">// key 2<br /></span><span style="color: #007700">}<br />function </span><span style="color: #0000BB">gen</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 0</span><span style="color: #007700">; </span><span style="color: #FF8000">// key 0<br /> </span><span style="color: #0000BB">yield from from</span><span style="color: #007700">(); </span><span style="color: #FF8000">// keys 0-2<br /> </span><span style="color: #0000BB">yield 4</span><span style="color: #007700">; </span><span style="color: #FF8000">// key 1<br /></span><span style="color: #007700">}<br /></span><span style="color: #FF8000">// pass false as second parameter to get an array [0, 1, 2, 3, 4]<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">iterator_to_array</span><span style="color: #007700">(</span><span style="color: #0000BB">gen</span><span style="color: #007700">()));<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> <div class="example-contents"><p>The above example will output:</p></div> <div class="example-contents screen"> <div class="cdata"><pre> array(3) { [0]=> int(1) [1]=> int(4) [2]=> int(3) } </pre></div> </div> </div> </div> <div class="example" id="example-290"> <p><strong>Example #6 Basic use of <strong class="command">yield from</strong></strong></p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">count_to_ten</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 1</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">yield 2</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">yield from </span><span style="color: #007700">[</span><span style="color: #0000BB">3</span><span style="color: #007700">, </span><span style="color: #0000BB">4</span><span style="color: #007700">];<br /> </span><span style="color: #0000BB">yield from </span><span style="color: #007700">new </span><span style="color: #0000BB">ArrayIterator</span><span style="color: #007700">([</span><span style="color: #0000BB">5</span><span style="color: #007700">, </span><span style="color: #0000BB">6</span><span style="color: #007700">]);<br /> </span><span style="color: #0000BB">yield from seven_eight</span><span style="color: #007700">();<br /> </span><span style="color: #0000BB">yield 9</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">yield 10</span><span style="color: #007700">;<br />}<br /><br />function </span><span style="color: #0000BB">seven_eight</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 7</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">yield from eight</span><span style="color: #007700">();<br />}<br /><br />function </span><span style="color: #0000BB">eight</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 8</span><span style="color: #007700">;<br />}<br /><br />foreach (</span><span style="color: #0000BB">count_to_ten</span><span style="color: #007700">() as </span><span style="color: #0000BB">$num</span><span style="color: #007700">) {<br /> echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$num</span><span style="color: #DD0000"> "</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> <div class="example-contents"><p>The above example will output:</p></div> <div class="example-contents screen"> <div class="cdata"><pre> 1 2 3 4 5 6 7 8 9 10 </pre></div> </div> </div> <div class="example" id="example-291"> <p><strong>Example #7 <strong class="command">yield from</strong> and return values</strong></p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">count_to_ten</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 1</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">yield 2</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">yield from </span><span style="color: #007700">[</span><span style="color: #0000BB">3</span><span style="color: #007700">, </span><span style="color: #0000BB">4</span><span style="color: #007700">];<br /> </span><span style="color: #0000BB">yield from </span><span style="color: #007700">new </span><span style="color: #0000BB">ArrayIterator</span><span style="color: #007700">([</span><span style="color: #0000BB">5</span><span style="color: #007700">, </span><span style="color: #0000BB">6</span><span style="color: #007700">]);<br /> </span><span style="color: #0000BB">yield from seven_eight</span><span style="color: #007700">();<br /> return </span><span style="color: #0000BB">yield from nine_ten</span><span style="color: #007700">();<br />}<br /><br />function </span><span style="color: #0000BB">seven_eight</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 7</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">yield from eight</span><span style="color: #007700">();<br />}<br /><br />function </span><span style="color: #0000BB">eight</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 8</span><span style="color: #007700">;<br />}<br /><br />function </span><span style="color: #0000BB">nine_ten</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">yield 9</span><span style="color: #007700">;<br /> return </span><span style="color: #0000BB">10</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$gen </span><span style="color: #007700">= </span><span style="color: #0000BB">count_to_ten</span><span style="color: #007700">();<br />foreach (</span><span style="color: #0000BB">$gen </span><span style="color: #007700">as </span><span style="color: #0000BB">$num</span><span style="color: #007700">) {<br /> echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$num</span><span style="color: #DD0000"> "</span><span style="color: #007700">;<br />}<br />echo </span><span style="color: #0000BB">$gen</span><span style="color: #007700">-></span><span style="color: #0000BB">getReturn</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> <div class="example-contents"><p>The above example will output:</p></div> <div class="example-contents screen"> <div class="cdata"><pre> 1 2 3 4 5 6 7 8 9 10 </pre></div> </div> </div> </div> </div> </div><hr /><div class="manualnavbar" style="text-align: center;"> <div class="prev" style="text-align: left; float: left;"><a href="language.generators.overview.html">Generators overview</a></div> <div class="next" style="text-align: right; float: right;"><a href="language.generators.comparison.html">Comparing generators with Iterator objects</a></div> <div class="up"><a href="language.generators.html">Generators</a></div> <div class="home"><a href="index.html">PHP Manual</a></div> </div></body></html>