Iteradores en PHP

Author
Por Darío Rivera
Publicado el en 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

Application Architect at Elentra Corp . Quality developer and passionate learner with 10+ years of experience in web technologies. Creator of EasyHttp , an standard way to consume HTTP Clients.

LinkedIn Twitter Instagram

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