## `foreach`

(PHP 4, PHP 5, PHP 7, PHP 8)

El constructor `foreach` proporciona un modo sencillo de iterar sobre arrays. `foreach` funciona sólo sobre arrays y objetos, y emitirá un error al intentar usarlo con una variable de un tipo diferente de datos o una variable no inicializada. Existen dos sintaxis:

    foreach (expresión_array as $valor)
        sentencias
    foreach (expresión_array as $clave => $valor)
        sentencias

La primera forma recorre el array dado por `expresión_array`. En cada iteración, el valor del elemento actual se asigna a `$valor` y el puntero interno del array avanza una posición (así en la próxima iteración se estará observando el siguiente elemento).

La segunda forma además asigna la clave del elemento actual a la variable `$clave` en cada iteración.

También es posible personalizar la iteración de objetos.

> Nota:

> En PHP 5, cuando `foreach` inicia su ejecución, el puntero interno del array se pone automáticamente en el primer elemento del array. Esto significa que no es necesario llamar la función reset() antes de un bucle `foreach`.

> Ya que `foreach` depende el puntero de array interno en PHP 5, cambiar éste dentro del bucle puede conducir a un comportamiento inesperado.

> En PHP 7, `foreach` no utiliza el puntero interno del array.

Para poder modificar directamente los elementos del array dentro de bucle, se ha de anteponer & a `$valor`. En este caso el valor será asignado por referencia.

`<?php
$array = array(1, 2, 3, 4);
foreach ($array as &$valor) {
$valor = $valor * 2;
}
// $array ahora es array(2, 4, 6, 8)
unset($valor); // rompe la referencia con el último elemento
?>`
Advertencia

La referencia del `$valor` y el último elemento del array permanecen aún después del bucle `foreach`. Se recomienda destruirlos con unset(). De lo contrario, se experimentará el siguiente funcionamiento:

`<?php
$array = array(1, 2, 3, 4);
foreach ($array as &$valor) {
$valor = $valor * 2;
}
// $array ahora es array(2, 4, 6, 8)
// sin unset($valor), $valor aún es una referencia al último elemento: $array[3]
foreach ($array as $clave => $valor) {
// $array[3] se actualizará con cada valor de $array...
echo "{$clave} => {$valor} ";
print_r($array);
}
// ...hasta que finalmente el penúltimo valor se copia al último valor
// salida:
// 0 => 2 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 2 )
// 1 => 4 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 4 )
// 2 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
// 3 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
?>`

Antes de PHP 5.5.0, referenciar `$valor` sólo es posible si el array iterado puede ser referenciado (es decir, si es una variable). El siguiente código solamente funciona a partir de PHP 5.5.0:

`<?php
foreach (array(1, 2, 3, 4) as &$valor) {
$valor = $valor * 2;
}
?>`

> Nota:

> `foreach` no soporta la capacidad de suprimir mensajes de error usando '@'.

Algunos ejemplos más para demostrar su uso:

`<?php
/* Ejemplo 1 de foreach: sólo el valor */
$a = array(1, 2, 3, 17);
foreach ($a as $v) {
echo "Valor actual de \$a: $v.\n";
}
/* Ejemplo 2 de foreach: valor (con su notación de acceso manual impreso con fines ilustrativos) */
$a = array(1, 2, 3, 17);
$i = 0; /* sólo para efectos ilustrativos */
foreach ($a as $v) {
echo "\$a[$i] => $v.\n";
$i++;
}
/* Ejemplo 3 de foreach: clave y valor */
$a = array(
"uno" => 1,
"dos" => 2,
"tres" => 3,
"diecisiete" => 17
);
foreach ($a as $k => $v) {
echo "\$a[$k] => $v.\n";
}
/* Ejemplo 4 de foreach: arrays multidimensionales */
$a = array();
$a[0][0] = "a";
$a[0][1] = "b";
$a[1][0] = "y";
$a[1][1] = "z";
foreach ($a as $v1) {
foreach ($v1 as $v2) {
echo "$v2\n";
}
}
/* Ejemplo 5 de foreach: arrays dinámicos */
foreach (array(1, 2, 3, 4, 5) as $v) {
echo "$v\n";
}
?>`

### Utilizando arrays anidados con list()

(PHP 5 >= 5.5.0, PHP 7, PHP 8)

PHP 5.5 añade la posibilidad de recorrer un array de arrays y utilizar el array interior en las variables del bucle proporcionando list() como el valor.

Por ejemplo:

`<?php
$array = [
[1, 2],
[3, 4],
];
foreach ($array as list($a, $b)) {
// $a contiene el primer elemento del array interior,
// y $b contiene el segundo elemento.
echo "A: $a; B: $b\n";
}
?>`

El resultado del ejemplo sería:

    A: 1; B: 2
    A: 3; B: 4

Puedes proporcionar menos elementos a list() de los que hay en el array interior, en cuyo caso los elementos sobrantes del array serán descartados:

`<?php
$array = [
[1, 2],
[3, 4],
];
foreach ($array as list($a)) {
// Observa que no hay $b en este caso.
echo "$a\n";
}
?>`

El resultado del ejemplo sería:

    1
    3

Se generará un notice si no hay suficientes elementos en el array para completar el list():

`<?php
$array = [
[1, 2],
[3, 4],
];
foreach ($array as list($a, $b, $c)) {
echo "A: $a; B: $b; C: $c\n";
}
?>`

El resultado del ejemplo sería:

    Notice: Undefined offset: 2 in example.php on line 7
    A: 1; B: 2; C:

    Notice: Undefined offset: 2 in example.php on line 7
    A: 3; B: 4; C:

### Historial de cambios

Versión | Descripción
--- | ---
7.0.0 | `foreach` ya no utiliza el puntero interno al array.
5.5.0 | Hacer referencia a `$valor` está admitido para expresiones. Anteriormente, solamente estaban admitidas las variables.
5.5.0 | El desempaquetamiento de arrays anidados con list() está admitido.