Blog de Gonzalo

GENERADORES EN PHP

Siempre he usado el for y el foreach para recorrer arrays en php pero he descubierto los generadores en php que permiten usar foreach para iterar datos de tal modo que no se necesite cargar ningún array en memoria o se requiera mucho tiempo para generarse. En su lugar se escribe una función generadora. En esta función generadora en vez devolver el valor con return se usa yield.
¿Pero qué es yield? Yield significa ceder y funciona de forma similar a return ya que devuelve un valor, pero en lugar de remover la función de la pila, Yield guarda su estado, de esta forma puede continuar por donde estaba si se le llama otra vez. No es posible devolver un valor desde un generador pero si que se puede emplear return sin un valor para terminar su ejecución.
Los generadores en php tienen la gran ventaja que no requieren demasiada memoria ya que antes necesitabas un array para recorrer lo y podría ocupar memoria pero con los generadores en php no es necesario.
Ejemplo básico:


function muestraArchivo($nombreArchivo){
    $archivo = fopen($nombreArchivo, 'r');
    while (($linea = fgets($archivo)) !== false){
        yield $linea;
    }
    fclose($archivo);
}
foreach (muestraArchivo('nombre_archivo.txt') as $linea){
    echo $linea;
}

En el ejemplo anterior la función "muestraArchivo" abre el archivo y hace "yield" en cada línea del archivo cuando se le ordena. Cada vez que se llama a generator, continúa desde donde lo dejó. Cuando se han leído todas las líneas el generador termina junto con la iteración.
Los generadores son especialmente útiles para calcular grandes conjuntos de datos y no requiere excesiva memoria para mostrar todos al mismo tiempo o cuando no se sabe si se necesitarán todos los resultados. Debido a la forma en que se procesan los resultados con los generadores, el uso de memoria se puede reducir al mínimo asignando la memoria sólo al resultado actual.
Ejemplo con base de datos:

function getArticles()
{

   $result = $this->db->query('SELECT * FROM articles');

   while($record = $result->fetch(PDO::FETCH_ASSOC)) {

       yield $this->mapToObject($record);

   }

}

foreach($model->getArticles() as $article)
 {
    echo $article->title;
}

En el ejemplo anterior se vería como usar los generadores con bases de datos. Espero que os haya servido.
Os recomiendo leer el post sobre generadores en javascript.

Compartir en twitter