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.