yield from
The yield from keyword is used in PHP to delegate the generation of values to another generator. This allows you to chain multiple generators together, creating
Introduction
yield from is an expression that lets one generator delegate to another iterable — another generator, an array, or any Traversable. Instead of looping over the inner source and re-yielding each item by hand, you write a single yield from and PHP forwards all of its values (and keys) to the caller for you.
This makes it easy to compose generators: you can build a large stream of values out of small, focused generator functions without ever materializing the whole sequence in memory. Introduced in PHP 7.0, yield from is the standard way to flatten nested generators.
This chapter covers the basic syntax, how keys are handled, how to capture a delegated generator's return value, and when delegation is the right tool.
Basic syntax
yield from appears inside a generator function and is followed by any iterable:
yield from $iterable; // generator, array, or TraversableHere is a minimal example that combines two generators into one stream:
<?php
function myGenerator()
{
yield "Hello";
yield "World";
}
function myOtherGenerator()
{
yield "!";
}
function myCombinedGenerator()
{
yield from myGenerator();
yield from myOtherGenerator();
}
foreach (myCombinedGenerator() as $value) {
echo $value . " ";
}myCombinedGenerator() does not produce any values of its own — it delegates entirely to the other two generators. Calling it yields the values from myGenerator() first, then those from myOtherGenerator(), so the foreach prints:
Hello World !You can freely mix delegation with regular yield statements in the same function:
<?php
function countToThree()
{
yield 1;
yield 2;
yield 3;
}
function countToFive()
{
yield from countToThree(); // delegates 1, 2, 3
yield 4; // then yields its own values
yield 5;
}
foreach (countToFive() as $value) {
echo $value . " ";
}
// Output: 1 2 3 4 5Delegating to arrays and other iterables
The source after yield from does not have to be a generator. Any array or Traversable works, which is handy for flattening fixed and lazy sequences together:
<?php
function items()
{
yield from ['apple', 'banana']; // an array
yield from ['cherry'];
}
foreach (items() as $item) {
echo $item . "\n";
}
// Output:
// apple
// banana
// cherryHow keys are handled
yield from preserves the keys of the inner iterable, not just the values. This is the most common gotcha: keys are not renumbered, so two delegated sources can produce duplicate keys.
<?php
function inner()
{
yield 'a' => 1;
yield 'b' => 2;
}
function outer()
{
yield from inner();
yield 'c' => 3;
}
foreach (outer() as $key => $value) {
echo "$key => $value\n";
}
// Output:
// a => 1
// b => 2
// c => 3Because keys are kept as-is, do not rely on a continuous 0, 1, 2, … sequence when delegating to integer-keyed sources — collect the values into an array with iterator_to_array($gen, false) if you need them re-indexed.
Capturing the inner generator's return value
A delegated generator can return a final value (separate from the values it yields). The yield from expression evaluates to that return value, which you can assign to a variable:
<?php
function inner()
{
yield 1;
yield 2;
return 'done';
}
function outer()
{
$result = yield from inner();
echo "Inner returned: $result\n";
yield 3;
}
foreach (outer() as $value) {
echo "Value: $value\n";
}
// Output:
// Value: 1
// Value: 2
// Inner returned: done
// Value: 3Note that the inner generator's return value is captured by yield from — it is not forwarded to the foreach loop. Only the yielded values (1, 2, 3) reach the consumer.
When to use yield from
Reach for yield from when you want to:
- Compose generators — build a pipeline out of small, single-purpose generator functions instead of one large function.
- Flatten nested structures — recursively walk trees or nested arrays and emit a single flat stream of values.
- Stay memory-efficient — values flow through lazily, one at a time, so you never hold the full sequence in memory.
Compared with manually re-yielding (foreach ($inner as $v) { yield $v; }), yield from is shorter, preserves keys automatically, and forwards the inner generator's return value — so prefer it whenever you are delegating to another iterable.
Related topics
- yield — the foundation of generators in PHP.
- foreach loop — how generator values are consumed.
- PHP functions and return — the building blocks behind generator functions.