Iteración de objetos

PHP 5 ofrece una manera para definir objetos, por lo que es posible recorrer una lista de elementos con, por ejemplo, una sentencia foreach. Por defecto, se utilizarán todas las propiedades visibles para la iteración.

Ejemplo #1 Iteración simple de un objeto

<?php
class MiClase
{
    public 
$var1 'valor 1';
    public 
$var2 'valor 2';
    public 
$var3 'valor 3';

    protected 
$protected 'variable protegida';
    private   
$private   'variable privada';

    function 
iterateVisible() {
       echo 
"MiClase::iterateVisible:\n";
       foreach (
$this as $clave => $valor) {
           print 
"$clave => $valor\n";
       }
    }
}

$clase = new MiClase();

foreach(
$clase as $clave => $valor) {
    print 
"$clave => $valor\n";
}
echo 
"\n";


$clase->iterateVisible();

?>

El resultado del ejemplo sería:

var1 => valor 1
var2 => valor 2
var3 => valor 3

MiClase::iterateVisible:
var1 => valor 1
var2 => valor 2
var3 => valor 3
protected => variable protegida
private => variable privada

Como se muestra en la salida, foreach recorre todas las propiedades visibles a las que se pueden acceder.

Para dar un paso más, se puede implementar la interfaz Iterator. Esto permite al objeto decidir cómo será iterado y qué valores estarán disponibles en cada iteración.

Ejemplo #2 Iteración de un objeto implementando Iterator

<?php
class MiIterador implements Iterator
{
    private 
$var = array();
    
    public function 
__construct($array)
    {
        if (
is_array($array)) {
            
$this->var $array;
        }
    }

    public function 
rewind()
    {
        echo 
"rebobinando\n";
        
reset($this->var);
    }

    public function 
current()
    {
        
$var current($this->var);
        echo 
"actual: $var\n";
        return 
$var;
    }

    public function 
key()
    {
        
$var key($this->var);
        echo 
"clave: $var\n";
        return 
$var;
    }

    public function 
next()
    {
        
$var next($this->var);
        echo 
"siguiente: $var\n";
        return 
$var;
    }

    public function 
valid()
    {
        
$clave key($this->var);
        
$var = ($clave !== NULL && $clave !== FALSE);
        echo 
"válido: $var\n";
        return 
$var;
    }

}

$valores = array(1,2,3);
$it = new MiIterador($valores);

foreach (
$it as $a => $b) {
    print 
"$a$b\n";
}
?>

El resultado del ejemplo sería:

rebobinando
válido: 1
actual: 1
clave: 0
0: 1
siguiente: 2
válido: 1
actual: 2
clave: 1
1: 2
siguiente: 3
válido: 1
actual: 3
clave: 2
2: 3
siguiente:
válido:

La interfaz IteratorAggregate se puede usar como alternativa para implementar todos los métodos de Iterator. IteratorAggregate solamente requiere la implementación de un único método, IteratorAggregate::getIterator(), el cual debería devolver una instancia de una clase que implemente Iterator.

Ejemplo #3 Iteración de un objeto implementando IteratorAggregate

<?php
class MiColección implements IteratorAggregate
{
    private 
$items = array();
    private 
$cuenta 0;

    
// Se requiere la definición de la interfaz IteratorAggregate
    
public function getIterator() {
        return new 
MiIterador($this->items);
    }

    public function 
add($valor) {
        
$this->items[$this->cuenta++] = $valor;
    }
}

$colección = new MiColección();
$colección->add('valor 1');
$colección->add('valor 2');
$colección->add('valor 3');

foreach (
$colección as $clave => $val) {
    echo 
"clave/valor: [$clave -> $val]\n\n";
}
?>

El resultado del ejemplo sería:

rebobinando
actual: valor 1
válido: 1
actual: valor 1
clave: 0
clave/valor: [0 -> valor 1]

siguiente: valor 2
actual: valor 2
válido: 1
actual: valor 2
clave: 1
clave/valor: [1 -> valor 2]

siguiente: valor 3
actual: valor 3
válido: 1
actual: valor 3
clave: 2
clave/valor: [2 -> valor 3]

siguiente:
actual:
válido:

Nota:

Para más ejemplos de iteradores, véase la extensión SPL.

Nota:

Los usuarios de PHP 5.5 y posteriores pueden investigar los generadores, los cuales posibilitan una forma alternativa de definir iteradores.