Iteradores en PHP

Author
By Darío Rivera
Posted on 2021-07-15 in PHP

Todos sabemos lo cómodo que es utilizar for, while y foreach al iterar sobre arrays. Este tipo de elementos del lenguaje están diseñados para recorrer arrays que no guarden en memoria grandes cantidades de datos. El problema, nuevamente, es que como son tan cómodos, sencillos y fáciles de implementar nos olvidamos de que existen mejores alternativas cuando trabajamos con datos que pueden tildar nuestros scripts.

Qué es un iterador ?

Un iterador es un objeto que permite recorrer los elementos de una colección. La interfaz estándar de un iterador en PHP es la siguiente.

interface Iterator extends Traversable {
    public function current();
    public function next();
    public function key();
    public function valid();
    public function rewind();
}
Método Descripción
current() Retorna el elemento actual
next() Se mueve al siguiente elemento
key() Retorna la llave del elemento actual.
valid() Verifica si la posición actual es válida
rewind() Rebobina el iterador al primer elemento

Cómo implementar un iterador en PHP?

Supongamos que queremos un iterador para recorrer solamente los elementos en posición par de un array. Por ejemplo, si el array es ['a', 'b', 'c', 'd'] solamente nos interesaría recorrer b y d. Para esto, vamos a crear un iterador desde la interfaz que provee PHP.

class EvenIterator implements \Iterator
{
    private array $collection = [];
    private int $key = 1;

    public function __construct(array $collection)
    {
        $this->collection = $collection;
    }

    public function current()
    {
        return $this->collection[$this->key()];
    }

    public function next(): void
    {
        $this->key += 2;
    }

    public function key(): int
    {
        return $this->key;
    }

    public function valid(): bool
    {
        return array_key_exists($this->key(), $this->collection);
    }

    public function rewind(): void
    {
        $this->key = 1;
    }
}

Con esto, podríamos recorrer de manera transparente un array de la siguiente forma.

$iterator = new EvenIterator(['a', 'b', 'c', 'd']);

while ($iterator->valid()) {
    echo $iterator->current() . PHP_EOL;
    $iterator->next();
}

Y obtendríamos el resultado esperado.

b
d

Incluso, dado que la interfaz Iterator extiende de Traversable podríamos recorrelo mediante un foreach con un resultado equivalente.

foreach ($iterator as $item) {
    echo $iterator->current() . PHP_EOL;
}

Acerca de Darío Rivera

Author

Ingeniero de desarrollo en PlacetoPay , Medellín. Darío ha trabajado por más de 6 años en lenguajes de programación web especialmente en PHP. Creador del microframework DronePHP basado en Zend y Laravel.

Sólo aquellos que han alcanzado el éxito saben que siempre estuvo a un paso del momento en que pensaron renunciar.