W3docs

yield

La palabra clave yield se usa en PHP para crear funciones generadoras que producen valores uno a uno, pausando y reanudando la ejecución según se necesiten.

Introducción

La palabra clave yield convierte una función PHP ordinaria en un generador — una función que produce una secuencia de valores de uno en uno, pausando después de cada valor y reanudándose donde se quedó cuando se solicita el siguiente valor. Esta página explica cómo funciona yield, cómo generar claves, cómo enviar valores de vuelta a un generador, la sintaxis de delegación yield from, y cuándo los generadores ahorran memoria en comparación con construir un array completo.

Una función se convierte en generador en el momento en que contiene al menos un yield. Llamarla no ejecuta el cuerpo — devuelve un objeto Generator. El cuerpo solo se ejecuta a medida que se itera, avanzando hasta el siguiente yield en cada paso. Como un generador implementa la interfaz Iterator, normalmente se consume con un bucle foreach.

Un primer generador

Cada yield entrega un valor al llamador y congela la función hasta que se solicita el siguiente valor.

php— editable, runs on the server

myGenerator() devuelve un objeto generador en lugar de ejecutarse de inmediato. El bucle foreach extrae valores de él: en cada iteración la función se ejecuta hasta el siguiente yield, emite ese valor y se pausa. La salida es:

Hello World !

A diferencia de una función que construye y devuelve un array con return, las tres cadenas nunca se almacenan en memoria al mismo tiempo — cada una se produce bajo demanda. Compara esto con cómo una función normal usa return para devolver un único valor y salir.

Generar claves

Un generador puede generar pares clave/valor con la sintaxis yield $key => $value, exactamente como un array asociativo. Las claves están disponibles dentro de foreach:

<?php

function settings()
{
  yield "host" => "localhost";
  yield "port" => 5432;
  yield "user" => "admin";
}

foreach (settings() as $key => $value) {
  echo "$key = $value\n";
}

Salida:

host = localhost
port = 5432
user = admin

Si no se proporcionan claves, PHP numera automáticamente los valores generados comenzando desde 0, igual que un array indexado.

Los generadores son perezosos: un rango eficiente en memoria

El verdadero beneficio de yield es que los valores se calculan solo cuando se necesitan. Un generador que produce un millón de números usa memoria constante, mientras que un array de un millón de números los reserva todos de antemano.

<?php

function gen_range($start, $end)
{
  for ($i = $start; $i <= $end; $i++) {
    yield $i;
  }
}

$sum = 0;
foreach (gen_range(1, 1000000) as $n) {
  $sum += $n;
}

echo $sum;

Salida:

500000500000

El bucle nunca construye un array [1, 2, …, 1000000]; solo existe un entero a la vez. Este es el patrón a utilizar cuando se leen archivos enormes línea por línea o se transmiten filas de una base de datos.

Devolver un valor desde un generador

Un generador también puede usar return para exponer un valor final (PHP 7+). El valor de retorno no forma parte de la iteración — se lee después con getReturn():

<?php

function counter()
{
  yield 1;
  yield 2;
  return "done";
}

$gen = counter();
foreach ($gen as $value) {
  echo $value . " ";
}
echo $gen->getReturn();

Salida:

1 2 done

Llamar a getReturn() antes de que el generador haya terminado de iterar lanza una excepción, así que siempre agótalo primero.

Enviar valores con send()

Los generadores son bidireccionales: una expresión yield también puede recibir un valor enviado desde el llamador mediante send(). Esta es la base de las corrutinas.

<?php

function echoTimes()
{
  while (true) {
    $received = yield;
    echo "Got: $received\n";
  }
}

$gen = echoTimes();
$gen->current();      // prime the generator (run up to the first yield)
$gen->send("a");
$gen->send("b");

Salida:

Got: a
Got: b

send($value) reanuda el generador, haciendo que la expresión yield pausada evalúe a $value, y luego se ejecuta hasta el siguiente yield.

Delegación con yield from

yield from (PHP 7+) genera todos los valores de otro generador, array o Traversable, aplanándolos en el actual sin necesidad de un bucle manual:

<?php

function inner()
{
  yield 2;
  yield 3;
}

function outer()
{
  yield 1;
  yield from inner();
  yield from [4, 5];
}

foreach (outer() as $value) {
  echo $value . " ";
}

Salida:

1 2 3 4 5 

Cuándo usar un generador

  • Secuencias grandes o ilimitadas — leer un archivo de varios gigabytes o un flujo infinito donde guardar todo en un array es imposible.
  • Valores costosos que quizás no necesites — si el consumidor podría detenerse antes (break), un generador evita calcular el resto.
  • Código de iteración más limpio — reemplazar una clase Iterator personalizada con una única función.

Evita los generadores cuando necesites acceso aleatorio ($arr[42]), contar resultados con count() de forma económica, o iterar los mismos datos varias veces — un generador solo puede recorrerse una vez. Para esos casos, construye un array normal, posiblemente con funciones PHP como array_map.

Práctica

Práctica
¿Cuál es la función de la palabra clave 'yield' en PHP?
¿Cuál es la función de la palabra clave 'yield' en PHP?
Was this page helpful?