PHP 5.6.0 released

foreach

(PHP 4, PHP 5)

La structure de langage foreach fournit une façon simple de parcourir des tableaux. foreach ne fonctionne que pour les tableaux et les objets, et émettra une erreur si vous tentez de l'utiliser sur une variable de type différent ou une variable non initialisée. Il existe deux syntaxes :

foreach (array_expression as $value){
    //commandes
}
foreach (array_expression as $key => $value){
    //commandes
}

La première forme passe en revue le tableau array_expression. À chaque itération, la valeur de l'élément courant est assignée à $value et le pointeur interne de tableau est avancé d'un élément (ce qui fait qu'à la prochaine itération, on accédera à l'élément suivant).

La seconde forme assignera en plus la clé de l'élément courant à la variable $key à chaque itération.

Il est possible de personnaliser l'itération sur des objets.

Note:

Lorsque foreach démarre, le pointeur interne du tableau est automatiquement ramené au premier élément du tableau. Cela signifie que vous n'aurez pas à faire appel à reset() avant foreach.

Vu que foreach utilise le pointeur interne du tableau à chaque itération, il conviendra d'en tenir compte lors d'une utilisation future du tableau dans votre code.

Vous pouvez modifier facilement les éléments d'un tableau en précédent $value d'un &. Ceci assignera une référence au lieu de copier la valeur.

<?php
$arr 
= array(1234);
foreach (
$arr as &$value) {
    
$value $value 2;
}
// $arr vaut maintenant array(2, 4, 6, 8)
unset($value); // Détruit la référence sur le dernier élément
?>

Le référencement de $value est seulement possible si le tableau parcouru peut être référencé (i.e. si c'est une variable). Le code suivant ne fonctionnera pas :

<?php
foreach (array(1234) as &$value) {
    
$value $value 2;
}
?>

Avertissement

La référence de $value et le dernier élément du tableau sont conservés après l'exécution de la boucle foreach. Il est recommandé de les détruire en utilisant la fonction unset().

Note:

foreach n'accepte pas l'opérateur de suppression des erreurs @.

Vous pouvez remarquer que les exemples suivants fonctionnent de manière identique :

<?php
$arr 
= array("un""deux""trois");
reset($arr);
while (list(, 
$value) = each($arr)) {
    echo 
"Valeur : $value<br />\n";
}

foreach (
$arr as $value) {
    echo 
"Valeur : $value<br />\n";
}
?>

Les exemples suivants sont aussi fonctionnellement identiques :

<?php
$arr 
= array("un""deux""trois");
reset($arr);
while (list(
$key$value) = each($arr)) {
    echo 
"Clé : $key; Valeur : $value<br />\n";
}

foreach (
$arr as $key => $value) {
    echo 
"Clé : $key; Valeur : $value<br />\n";
}
?>

Voici quelques exemples de plus :

<?php
/* exemple foreach 1 : la valeur seulement */

$a = array(12317);

foreach (
$a as $v) {
    echo 
"Valeur courante de \$a: $v.\n";
}

/* exemple foreach 2 : la valeur et sa clé d'index */

$a = array(12317);

$i 0/* uniquement pour l'illustration */

foreach ($a as $v) {
    echo 
"\$a[$i] => $v.\n";
    
$i++;
}

/* exemple foreach 3 : la clé et la valeur */

$a = array(
    
"un" => 1,
    
"deux" => 2,
    
"trois" => 3,
    
"dix-sept" => 17
);

foreach (
$a as $k => $v) {
    echo 
"\$a[$k] => $v.\n";
}

/* exemple foreach 4 : tableaux multidimensionnels */
$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";
    }
}

/* exemple foreach 5 : tableaux dynamiques */

foreach (array(12345) as $v) {
    echo 
"$v\n";
}
?>

Extraction des tableaux internes avec list()

(PHP 5 >= 5.5.0)

PHP 5.5 ajout la possibilité d'itérer dans un tableau de tableaux, et d'en extraire les tableaux internes dans des variables, en fournissant une liste list() comme valeur.

Par exemple :

<?php
$array 
= [
    [
12],
    [
34],
];

foreach (
$array as list($a$b)) {
    
// $a contient le premier élément du tableau interne,
    // et $b contient le second élément.
    
echo "A: $a; B: $b\n";
}
?>

L'exemple ci-dessus va afficher :

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

Vous pouvez fournir moins d'éléments dans la fonction list() qu'il n'y en a dans le tableau interne, auquel cas, les valeurs du tableau les plus à droite seront ignorées :

<?php
$array 
= [
    [
12],
    [
34],
];

foreach (
$array as list($a)) {
    
// Notez qu'il n'y a pas de $b ici.
    
echo "$a\n";
}
?>

L'exemple ci-dessus va afficher :

1
3

Une notification sera générée s'il n'y a pas assez d'éléments dans le tableau pour remplir la fonction list() :

<?php
$array 
= [
    [
12],
    [
34],
];

foreach (
$array as list($a$b$c)) {
    echo 
"A: $a; B: $b; C: $c\n";
}
?>

L'exemple ci-dessus va afficher :


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: 

add a note add a note

User Contributed Notes 19 notes

up
60
adam dot sindelar at gmail dot com
6 years ago
You can also use the alternative syntax for the foreach cycle:

<?php
foreach($array as $element):
 
#do something
endforeach;
?>

Just thought it worth mentioning.
up
29
php at darkain dot com
1 year ago
"Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset()."

I cannot stress this point of the documentation enough! Here is a simple example of exactly why this must be done:

<?php
$arr1
= array("a" => 1, "b" => 2, "c" => 3);
$arr2 = array("x" => 4, "y" => 5, "z" => 6);

foreach (
$arr1 as $key => &$val) {}
foreach (
$arr2 as $key => $val) {}

var_dump($arr1);
var_dump($arr2);
?>

The output is:
array(3) { ["a"]=> int(1) ["b"]=> int(2) ["c"]=> &int(6) }
array(3) { ["x"]=> int(4) ["y"]=> int(5) ["z"]=> int(6) }

Notice how the last index in $arr1 is now the value from the last index in $arr2!
up
27
tedivm at tedivm dot com
5 years ago
foreach and the while/list/each methods are not completely identical, and there are occasions where one way is beneficial over the other.

<?php
$arr
= array(1,2,3,4,5,6,7,8,9);

foreach(
$arr as $key=>$value)
{
    unset(
$arr[$key + 1]);
    echo
$value . PHP_EOL;
}
?>
Output:
1 2 3 4 5 6 7 8 9

<?php
$arr
= array(1,2,3,4,5,6,7,8,9);

while (list(
$key, $value) = each($arr))
{
    unset(
$arr[$key + 1]);
    echo
$value . PHP_EOL;
}
?>
Output:
1 3 5 7 9


[EDIT BY danbrown AT php DOT net: Contains a typofix by (scissor AT phplabs DOT pl) on 30-JAN-2009.]
up
4
nehuen
4 months ago
foreach by reference internally deleted and created a new reference in each iteration, so it is not possible to directly use this value as a variable parameter values​​, look at the following example where the problem is observed and a possible solution:

<?php
class test
{
    private
$a = false;
    private
$r = null;
    public function
show(&$v)
    {
        if(!
$this->a)
        {
           
$this->a = true;
           
$this->r = &$v;
        }
       
var_dump($this->r);
    }
    public function
reset()
    {
       
$this->a = false;   
    }
}

$t = new test();

$a = array(array(1,2),array(3,4),array(5,6));
foreach(
$a as &$p)
   
$t->show($p);
   
/* Output obtain:
    array (size=2)
      0 => int 1
      1 => int 2
    array (size=2)
      0 => int 1
      1 => int 2
    array (size=2)
      0 => int 1
      1 => int 2
*/
 
 
$t->reset();
  foreach(
$a as $p)
  {
   
$b = &$p;
   
$t->show($b);
  }
 
/* Output obtain:
    array (size=2)
      0 => int 1
      1 => int 2
    array (size=2)
      0 => int 3
      1 => int 4
    array (size=2)
      0 => int 5
      1 => int 6
*/
up
6
Oleg englishman at bigmir dot net
3 years ago
For those who'd like to traverse an array including just added elements (within this very foreach), here's a workaround:

<?php
$values
= array(1 => 'a', 2 => 'b', 3 => 'c');
while (list(
$key, $value) = each($values)) {
    echo
"$key => $value \r\n";
    if (
$key == 3) {
       
$values[4] = 'd';
    }
    if (
$key == 4) {
       
$values[5] = 'e';
    }
}
?>

the code above will output:

1 => a
2 => b
3 => c
4 => d
5 => e
up
2
Alastair Hole
4 months ago
What happened to this note:
"Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it."

Is this no longer the case?
It seems only to remain in the Serbian documentation: http://php.net/manual/sr/control-structures.foreach.php
up
6
dtowell
2 years ago
References created by foreach hang around past their best-used-by date. For example, the following:

<?php
$a
= array('abe','ben','cam');
foreach (
$a as $k=>&$n)
   
$n = strtoupper($n);
foreach (
$a as $k=>$n) // notice NO reference here!
   
echo "$n\n";
print_r($a);
?>

will result in:

ABE
BEN
BEN
Array
(
    [0] => ABE
    [1] => BEN
    [2] => BEN
)
up
5
nobody at nobody dot com
2 years ago
<?php
$d3
= array('a'=>array('b'=>'c'));
foreach(
$d3['a'] as &$v4){}
foreach(
$d3 as $v4){}
var_dump($d3);
?>
will get something look like this:
array(1) {
  ["a"]=>
  array(1) {
    ["b"]=>
    &array(1) {
      ["b"]=>
      *RECURSION*
    }
  }
}
then you try to walk some data with this array.
the script run out of memory and connect reset by peer

the document says:
Warning
Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

so what I learn is that NEVER ignore """Warning""" in document....
up
3
billardmchl at aol dot com
3 years ago
This function find well the words, add well adds a () around short words, but the
array at the end of th function is the same as at the beginning.

<?php
function isole_mots($chaine)
{
   
$chaine = "le petit chat est fou";
   
$mots = preg_split('/[!,-.;?:()[ ]/', $chaine, -1, PREG_SPLIT_NO_EMPTY);
    foreach (
$mots as $mot)
    {
        if (
strlen($mot) <= 3)
           
$mot = "(".$mot.")";
    print
" inside foreach $mot <br>";
    }
print
"after foreach array mots";   
   
print_r($mots);
    die();
    return
$mots;
}
?>

inside foreach (le)
inside foreach petit
inside foreach chat
inside foreach (est)
inside foreach (fou)
after foreach array motsArray ( [0] => le [1] => petit [2] => chat [3] => est [4] => fou )
up
-1
liam666 at donnelly-house dot net
2 months ago
This is a decent, simple, and easy way to reference other values of an associative array when using foreach. (effective "next", "prev", etc.)
The only care that needs to be taken is if the array is HUGE in size, so you don't run into memory use problems. (and potential speed issues)

This example uses the 'primary' array, $aPublishSeq, which is ksort-ed to put the array in order according to the associative keys. The array is then copied using a foreach loop to make a duplicate array where the key and value order correspond to the first array, but the keys are sequential numeric starting at zero.

ksort ($aPublishSeq, SORT_STRING);     // put them all in the right order keeping array keys
foreach ($aPublishSeq as $aValue)
   $aPublishIdx[] = $aValue;          // duplicate array using corresponding sequential numeric keys

Now, in the usage foreach loop, an index variable is used to keep in sync with the associative array.

$PubIdx = -1;     // start at -1 to start at 0 below

foreach ($aPublishSeq as $sKey => $sValue) {

      ++$PubIdx;     // index into $aPublishIdx array of corresponding element in $aPublishSeq array (for "next" element check, etc.)

   echo $aPublishIdx[$PubIdx  - 1]     // previous array value
   echo $aPublishIdx[$PubIdx]          // current array value
   echo $aPublishIdx[$PubIdx  + 1]     // next array value

....

It's simple, but it works, and without much muss or fuss.
up
-2
Delian Krustev
1 year ago
I want to add some inline comments to dtowell's piece of code about the iteration by reference:

<?php

$a
= array('abe','ben','cam');

foreach (
$a as $k=>&$n)
   
$n = strtoupper($n);

# At the end of this cycle the variable $n refers to the same memory as $a[2]
# So when the second "foreach" assigns a value to $n :

foreach ($a as $k=>$n) // notice NO reference here!
   
echo "$n\n";

# it is also modifying $a[2] .
# So on the three repetitions of the second "foreach" the array will look like:
# 1. ('abe','ben','abe') - assigned the value of the first element to the last element
# 2. ('abe','ben','ben') - assigned the value of the second element to the last element
# 3. ('abe','ben','ben') - assigned the value of the third element to itself

print_r($a);
?>
up
-3
Anonymous
11 months ago
[quote]
I want to add some inline comments to dtowell's piece of code about the iteration by reference:

<?php

$a
= array('abe','ben','cam');

foreach (
$a as $k=>&$n)
   
$n = strtoupper($n);

# At the end of this cycle the variable $n refers to the same memory as $a[2]
# So when the second "foreach" assigns a value to $n :

foreach ($a as $k=>$n) // notice NO reference here!
   
echo "$n\n";

# it is also modifying $a[2] .
# So on the three repetitions of the second "foreach" the array will look like:
# 1. ('abe','ben','abe') - assigned the value of the first element to the last element
# 2. ('abe','ben','ben') - assigned the value of the second element to the last element
# 3. ('abe','ben','ben') - assigned the value of the third element to itself

print_r($a);
?>
[/quote]

To resolve this problem - should always use unset after foreach:
<?php

$array
= array('abe','ben','cam');

foreach (
$array as $key=>&$val ) {}
unset(
$key); unset($val);
foreach (
$array as $key=>$val ) {}
unset(
$key); unset($val);

print_r($array);
up
-3
mvaqasuddin at gmail dot com
6 months ago
more control over foreach you can use these code for zebra stripping in table class or other.

foreach ( $data as $key => $row ) {
                   
                    $class = fmod( $key,2 ) ? 'even' : 'odd';

                    echo '<tr class = "'.$class.'" >';

                    foreach ( $row as $cell ) {
                      
                        echo "<td>$cell</td>";
                   
                    }

                    echo "</tr>";
                }
up
-12
Luke at chaoticlogic dot net
7 years ago
Alright, I had a little error. I had one foreach() declaration, and then another foreach() declaration.

They went:
<?php
//$connections is an array of Socket resources
foreach ($connections as $key => &$value) {
   
//the code here is impertinent

}

//$users is an associative array
foreach ($users as $key => &$value) {
   
//the code here is impertinent
}
?>

Alright, now, what error was produced as a result of this?
This one:
"Warning: Cannot use scalar value as array in filename.php on line 69."

I then realized something; the reason for this came from the fact that I used $key, and $value for both of them in the exact same way.

As a response to this, I've developed two ways to fix this:
<?php
//add this to the end of every foreach() you use
unset($key,$value)
?>

OR

Simply use different variables for each one.
up
-14
Ashus
1 year ago
If you wondered how to create a list of all possible combinations of variable amount of arrays (multiple foreach), you might use this:

<?php

$a
[0] = array('a1','a2');
$a[1] = array('b1','b2','b3');
$a[2] = array('c1','c2');

function
getAllCombinations($a,$i,$s)
    {
    foreach (
$a[$i] as $v)
        {
        if (!isset(
$a[$i+1]))
            {
            echo
$s.$v."\n";
            } else {
           
getAllCombinations($a,$i+1,$s.$v);
            }
        }
    return
$s;
    }

echo
getAllCombinations($a,0,'');

?>

the result:

a1b1c1
a1b1c2
a1b2c1
a1b2c2
a1b3c1
a1b3c2
a2b1c1
a2b1c2
a2b2c1
a2b2c2
a2b3c1
a2b3c2
up
-16
Voitcus at wp dot pl
2 years ago
You can even iterate through "dynamic" arrays that do not physically exist, but are objects that implement Iterator interface. They don't need to be stored in memory when foreach starts.

Consider the array that contains some values (I called it $allValues in the example below) and we want to have only some of them (eg. the ones that are dividable by 2). I create an object that would serve as dynamic array, that means it would "dynamically update" its values together with $allValues. The main advantage is that I store only one array, and it's the only array I serialize.

An object of MyIter class will not contain any values itself:
<?php
class MyIter implements Iterator { // you can implement ArrayAccess and Countable interfaces too, this will make class MyIter behave like a "real" array
 
private $position = 0; // an internal position of the current element
  // please note that $position has nothing common with $allValues!

 
private function getTable(){ // prepare a temporary "static" table of all objects in the class
   
global $allValues;
   
$result=array(); // temporary variable
   
foreach($allValues as $obj){
      if(
$obj % 2 == 0) // check if the value is even
       
$result[]=$obj; // if yes, I want it
     
}
    return
$result;
  }   

 
// the all below declared methods are public and belong to the Iterator interface
 
function rewind() { // a method to start iterating
   
$this->position = 0; // just move to the beginning
 
}

  function
current() { // retrieves the current element
   
$table=$this->getTable(); // let us prepare a table
   
return $table[$this->position]; // and return the current element
 
}

  function
key() { // retrieves the current element's key
   
return $this->position; // this is used by foreach(... as $key=>$value), not important here
 
}

  function
next() { // move to next element
   
++$this->position;
  }

  function
valid() { // check if the current element is valid (ie. if it exists)
   
return array_key_exists($this->position, $this->getTable());
  }
}
// end of class

// now prepare the array of 12 elements
$allValues=array(0,1,2,3,4,5,6,7,8,9,10,11);

//we would like to have a dynamic array of all even values
$iterator=new MyIter();

foreach(
$iterator as $value){
  echo
$value."<br />";
}
?>
This will result in:
0
2
4
6
8
10

(You may also like to see what var_dump($iterator) produces).

Another great advantage is that you can modify the main table "on-the-fly" and it has its impact. Let us modify the last foreach loop:
<?php
// ...all above shall stay as it was
foreach($iterator as $value){
  echo
$value."<br />";
  if(
$value==6){
   
$allValues=array(2,3);
    echo
"I modified source array!<br />";
  }
}
?>
This produces now:
0
2
4
6
I modified source array!

However, if you feel it is rather a catastrophic disadvantage (maybe for example, it shows the values 0, 4, and 6 which were removed when we reached 6), and wish to have a "static" array that will iterate even in modified objects, just call getTable() in rewind() method and save it in temporary (private perhaps) field. In my example getTable() is called every iteration, and it calls another foreach through $allValues, which together might be time-consuming. Consider what you need.
up
-24
simplex
7 years ago
"As of PHP 5, you can easily modify array's elements by preceding $value with &. This will assign reference instead of copying the value."

There are cases where array_walk or array_map are inadequate (conditional required) or you're just too lazy to write a function and pass values to it for use with array_map...

My solution to foreach for php 4 and 5 to modify values of an array directly:

<?php

$testarr
= array("a" => 1, "b" => 2, "c" => 3, "d" => 4);

$testarr_keys = array_keys($testarr);
$testarr_values = array_values($testarr);

for (
$i = 0; $i <= count($testarr) - 1; $i++) {
   
$testarr[$testarr_keys[$i]] = $testarr_values[$i] * 2;
}

print_r($testarr);
?>
up
-5
sainthyoga2003 at gmail dot com
4 months ago
Note that prior to PHP 5.5 you will get a T_LIST parse error for:
<?php
foreach($list as list($a, $b)) {...
?>
up
-31
php at electricsurfer dot com
11 years ago
[Ed Note:  You can also use array_keys() so that you don't have to have the $value_copy variable --alindeman at php.net]

I use the following to modify the original values of the array:

<?php
foreach ($array as $key=>$value_copy)
{
    
$value =& $array[$key];
    
// ...
    
$value = 'New Value';
}
?>
To Top