Iteradores en PHP

Los iteradores en PHP son una herramienta fundamental cuando necesitamos procesar grandes volúmenes de información sin saturar la memoria. Su magia está en que recorren los datos de manera secuencial y controlada, cargando en memoria solo el elemento actual. Esto los convierte en una opción ligera y flexible para tareas como la generación de informes o la renderización de vistas complejas.

En lugar de manipular manualmente índices o punteros, los iteradores proporcionan un conjunto de métodos estándar para desplazarse por los datos, simplificando la lógica y mejorando la legibilidad del código.

📖 Imagina un iterador como un “control remoto” que te permite pasar página por página de un libro, sin necesidad de que memorices el número de cada una.

PHP ya incluye una serie de iteradores listos para usar dentro de la SPL (Standard PHP Library), como:

  • ArrayIterator → Iterar arrays como objetos.

  • DirectoryIterator → Iterar directorios y sus archivos.

  • FilterIterator → Iterar filtrando datos.

  • RecursiveIterator → Iterar estructuras jerárquicas (carpetas, árboles, etc.).

ArrayIterator

ArrayIterator es una clase incorporada en PHP que te permite recorrer y manipular arrays u objetos como si fueran colecciones avanzadas. No solo facilita la navegación, sino que también ofrece métodos adicionales para acceder, modificar y controlar los elementos de manera más sofisticada que con un simple foreach.

🏗️ Interfaces que implementa

  • Iterator → Navegación básica (current, key, next, rewind, valid).

  • ArrayAccess → Acceso tipo array (offsetGet, offsetSet, etc.).

  • SeekableIterator → Permite saltar directamente a una posición específica.

  • Countable → Contar elementos fácilmente con count().

  • Serializable → Serializar y deserializar datos para almacenamiento o transferencia.

💡 En pocas palabras, ArrayIterator es como un foreach con esteroides: más control, más flexibilidad y más poder sobre tus datos.

Métodos de ArrayIterador

MétodoDescripción
current()Retorna el elemento actual
key()Retorna la clave actual
next()Avanza al siguiente elemento
rewind()Vuelve al primer elemento
valid()Verifica si la posición actual es válida
offsetExists($offset)Verifica si existe un índice
offsetGet($offset)Obtiene valor por índice
offsetSet($offset, $value)Establece valor en índice
offsetUnset($offset)Elimina elemento por índice
seek($position)Salta a una posición específica
count()Cuenta los elementos
serialize()Serializa el ArrayIterator
unserialize($data)Deserializa datos
asort($flags = SORT_REGULAR)Ordena por valores manteniendo claves
ksort($flags = SORT_REGULAR)Ordena por claves
uasort($callback)Ordena por valores con función personalizada
natcasesort()Ordenamiento natural insensible a mayúsculas
natsort()Ordenamiento natural
getArrayCopy()Retorna una copia del array interno
getFlags()Obtiene las banderas configuradas
setFlags($flags)Establece banderas de comportamiento
append($value)Agrega un elemento al final

Ejemplos de uso de ArrayIterator

$frutas = ['manzana', 'banana', 'naranja', 'uva'];
$iterator = new ArrayIterator($frutas);

// Iterar manualmente
while ($iterator->valid()) {
    echo $iterator->key() . ': ' . $iterator->current() . "\\n";
    $iterator->next();
}

Otro Ejemplo:

$datos = ['a' => 1, 'b' => 2, 'c' => 3];
$iterator = new ArrayIterator($datos);

// Contar elementos
echo "Total elementos: " . $iterator->count() . "\\n";

// Buscar un valor
$iterator->rewind();
while ($iterator->valid()) {
    if ($iterator->current() == 2) {
        echo "Encontrado valor 2 en clave: " . $iterator->key() . "\\n";
        break;
    }
    $iterator->next();
}

// Ordenar (modifica el array original)
$iterator->asort(); // Ordenar por valores
foreach ($iterator as $k => $v) {
    echo "$k: $v\\n";
}

Uso avanzado - Clase personalizada

class ColeccionUsuarios implements IteratorAggregate
{
    private $usuarios = [];

    public function agregar($usuario) {
        $this->usuarios[] = $usuario;
    }

    public function getIterator() {
        return new ArrayIterator($this->usuarios);
    }
}

$coleccion = new ColeccionUsuarios();
$coleccion->agregar(['nombre' => 'Ana', 'edad' => 25]);
$coleccion->agregar(['nombre' => 'Carlos', 'edad' => 32]);

foreach ($coleccion as $usuario) {
    echo $usuario['nombre'] . " - " . $usuario['edad'] . " años\\n";
}

DirectoryIterator

El iterador DirectoryIterator nos ayuda a iterar las carpetas y subcarpetas existentes en una ruta, de esta manera podemos obtener la información de ca carpeta y los archivos existentes en esta carpeta.

Métodos más útiles

MétodoDescripción
getFilename()Nombre del archivo o directorio
getPathname()Ruta completa
isFile()Devuelve true si es un archivo
isDir()Devuelve true si es un directorio
isReadable()Si el archivo es legible
getSize()Tamaño en bytes
getExtension()Extensión del archivo
isDot()Devuelve true si es "." o ".."

Ejemplo básico:

<?php
$path = "/var/www/html";

$dir = new DirectoryIterator($path);

foreach ($dir as $file) {
    if ($file->isDot()) continue; // Ignora "." y ".."

    echo "Nombre: " . $file->getFilename() . PHP_EOL;
}

Ejemplo con filtrado

<?php
$path = "/var/www/html";

foreach (new DirectoryIterator($path) as $file) {
    if ($file->isDot()) continue;

    if ($file->isFile() && $file->getExtension() === 'php') {
        echo $file->getFilename() . " (" . $file->getSize() . " bytes)" . PHP_EOL;
    }
}

Ejemplo para listar subdirectorios

<?php
$path = "/var/www/html";

foreach (new DirectoryIterator($path) as $file) {
    if ($file->isDot()) continue;

    if ($file->isDir()) {
        echo "[DIR] " . $file->getFilename() . PHP_EOL;
    }
}

FilterIterator

Este iterador permite permite filtrar elementos durante la iteración sobre otra colección o iterador, sin tener que recorrer todo y aplicar un if manualmente dentro de un foreach.

Recibe como entrada otro iterador que contiene toda la data, cada ves que corre el filteriterator y cada vez que avanza se ejecuta accept y solo devuelve los que al entrar en accept devuelva un true.

Ejemplo básico: filtrar números pares

<?php
class EvenNumbersFilter extends FilterIterator {
    public function accept(): bool {
        return $this->current() % 2 === 0;
    }
}

$numbers = new ArrayIterator([1, 2, 3, 4, 5, 6]);
$evenNumbers = new EvenNumbersFilter($numbers);

foreach ($evenNumbers as $number) {
    echo $number . PHP_EOL;
}

Ejemplo con DirectoryIterator: solo archivos .php

<?php
class PhpFileFilter extends FilterIterator {
    public function accept(): bool {
        return $this->current()->isFile() &&
               $this->current()->getExtension() === 'php';
    }
}

$dir = new DirectoryIterator(__DIR__);
$phpFiles = new PhpFileFilter($dir);

foreach ($phpFiles as $file) {
    echo $file->getFilename() . PHP_EOL;
}

RecursiveIterator

Este iterador permite recorrer la estructura de arreglos bidimensionales perfecto para recorrer json.

Es un tipo especial de iterador que no solo recorre elementos de un nivel, sino que sabe si un elemento tiene "hijos" y permite recorrerlos recursivamente.

Métodos que define la interfaz RecursiveIterator

Todo iterador que implemente esta interfaz debe incluir:

  • hasChildren() → Indica si el elemento actual tiene elementos anidados.

  • getChildren() → Devuelve un nuevo iterador para recorrer los hijos.

  • Además, hereda los métodos de Iterator:

    • current() → Elemento actual.

    • key() → Clave del elemento actual.

    • next() → Avanzar al siguiente elemento.

    • rewind() → Reiniciar el recorrido.

    • valid() → Comprobar si hay más elementos.

Ejemplo

<?php
$data = [
    "frutas" => ["manzana", "pera"],
    "verduras" => ["zanahoria", "apio"],
    "cereales" => ["arroz" => ["blanco", "integral"]]
];

$iterator = new RecursiveArrayIterator($data);

foreach ($iterator as $key => $value) {
    if ($iterator->hasChildren()) {
        echo "[$key]:\\n";
        foreach ($iterator->getChildren() as $child) {
            echo "  - $child\\n";
        }
    } else {
        echo "$key => $value\\n";
    }
}

Salida:
[frutas]:
  - manzana
  - pera
[verduras]:
  - zanahoria
  - apio
[cereales]:
  - Array

Uso con RecursiveIteratorIterator

<?php
$data = [
    "frutas" => ["manzana", "pera"],
    "verduras" => ["zanahoria", "apio"],
    "cereales" => ["arroz" => ["blanco", "integral"]]
];

$recursiveIterator = new RecursiveArrayIterator($data);
$iterator = new RecursiveIteratorIterator($recursiveIterator);

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

Salida: 
0 => manzana
1 => pera
0 => zanahoria
1 => apio
0 => blanco
1 => integral

Conclusión

Los iteradores en PHP no solo hacen que el manejo de grandes volúmenes de datos sea más eficiente, sino que también nos permiten escribir código más limpio, legible y mantenible.
Ya sea que trabajes con colecciones simples o estructuras complejas, entender y aprovechar las clases de iteradores que ofrece PHP puede marcar la diferencia en el rendimiento y la claridad de tus aplicaciones.

💡 La próxima vez que necesites recorrer datos, recuerda que no todo es foreach: los iteradores pueden ser tu mejor aliado.

0
Subscribe to my newsletter

Read articles from Alejandro Benjumea Aguirre directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Alejandro Benjumea Aguirre
Alejandro Benjumea Aguirre

¡Hola! Soy Alejandro Benjumea Aguirre, un apasionado desarrollador de software con experiencia en el desarrollo de aplicaciones web y tecnologías backend. Actualmente, trabajo como desarrollador junior en una empresa que desarrolla soluciones tecnológicas para el sector salud. Tengo una sólida formación en análisis y desarrollo de sistemas de información, habiendo egresado del SENA, y actualmente estoy cursando Ingeniería en Sistemas en la UNAD. Mi objetivo es seguir creciendo como desarrollador backend, contribuir a proyectos de código abierto y mejorar mis habilidades en el uso de tecnologías modernas.