PHP
downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

foreach> <do-while
Last updated: Fri, 23 Jan 2009

view this page in

for

Les boucles for sont les boucles les plus complexes en PHP. Elles fonctionnent comme les boucles for du langage C. La syntaxe des boucles for est la suivante :

for (expr1; expr2; expr3)
    commandes

La première expression (expr1) est évaluée (exécutée), quoi qu'il arrive au début de la boucle.

Au début de chaque itération, l'expression expr2 est évaluée. Si l'évaluation vaut TRUE, la boucle continue et l'instruction est exécutée. Si l'évaluation vaut FALSE, l'exécution de la boucle s'arrête.

À la fin de chaque itération, l'expression expr3 est évaluée (exécutée).

Les expressions peuvent éventuellement être laissées vides ou peuvent contenir plusieurs expressions séparées par des virgules. Dans expr2, toutes les expressions séparées par une virgule sont évaluées mais le résultat est obtenu depuis la dernière partie. Si l'expression expr2 est laissée vide, cela signifie que c'est une boucle infinie (PHP considère implicitement qu'elle vaut TRUE, comme en C). Cela n'est pas vraiment très utile, à moins que vous souhaitiez terminer votre boucle par l'instruction conditionnelle break.

Considérons les exemples suivants. Tous affichent les chiffres de 1 jusqu'à 10 :

<?php
/* exemple 1 */

for ($i 1$i <= 10$i++) {
    echo 
$i;
}

/* exemple 2 */

for ($i 1; ; $i++) {
    if (
$i 10) {
        break;
    }
    echo 
$i;
}

/* exemple 3 */

$i 1;
for (; ; ) {
    if (
$i 10) {
        break;
    }
    echo 
$i;
    
$i++;
}

/* exemple 4 */

for ($i 1$j 0$i <= 10$j += $i, print $i$i++);
?>

Bien évidemment, le premier exemple est le plus simple de tous (ou peut être le quatrième), mais vous pouvez aussi pensez qu'utiliser une expression vide dans une boucle for peut être utile parfois.

PHP supporte aussi la syntaxe alternative suivante pour les boucles for :

for (expr1; expr2; expr3):
    commandes
    ...
endfor;

Beaucoup de personnes ont l'habitude d'itérer grâce à des tableaux, comme dans l'exemple ci dessous.

<?php
/*
 * Ceci est un tableau avec des données que nous voulons modifier
 * au long de la boucle
*/
$people = Array(
        Array(
'name' => 'Kalle''salt' => 856412),
        Array(
'name' => 'Pierre''salt' => 215863)
        );

for(
$i 0$i sizeof($people); ++$i)
{
    
$people[$i]['salt'] = rand(000000999999);
}
?>

Le problème se situe dans le deuxième argument de l'expression for. Ce code peut être lent parce qu'il doit caclculer la taille du tableau à chaque itération. Etant donné que la taille ne change jamais, il peut facilement être optimisé en utilisant une variable intermédiaire pour stocker la taille et en l'utilisant dans la boucle à la place de sizeof. L'exemple ci-dessous illustre ce cas :

<?php
$people 
= Array(
        Array(
'name' => 'Kalle''salt' => 856412),
        Array(
'name' => 'Pierre''salt' => 215863)
        );

for(
$i 0$size sizeof($people); $i $size; ++$i)
{
    
$people[$i]['salt'] = rand(000000999999);
}
?>



foreach> <do-while
Last updated: Fri, 23 Jan 2009
 
add a note add a note User Contributed Notes
for
Steven
11-Jan-2009 06:50
Alternating form rows:

<?php

$rows
= 4;

echo
'<table><tr>';

for(
$i = 0; $i < 10; $i++){
    echo
'<td>' . $i . '</td>';
    if((
$i + 1) % $rows == 0){
        echo
'</tr><tr>';
    }
}

echo
'</tr></table>';

?>

Changing $rows will change how many columns are in a row.
dkimbel13 at gmail dot com
07-Jan-2009 11:41
Just a note on looping through an array using the for() loop.

with the array...
<?php $array = array("value1","value2","value3"); ?>

then...
<?php
for(reset($array),current($array),next($array){
    echo(
"Element ".key($array)." contains ".current($array)."<br/>";
}
?>

is the equivalent of...
<?php
for($i=0;$i<count($array);$i++){
    echo(
"Element $i contains $array[$i]<br/>");
}
?>

I don't know if there is any advantage, just thought I would mention it.
alexander gavazov
03-Jul-2008 12:29
<?php
// Better variant
$some_arr = array('a', 'b', 'c', 'd', 'e');
for (
$i = 0, $cnt = count($some_arr); $i < $cnt; $i++) {
 print
$some_arr[$i] . "\n";
 unset(
$some_arr[$i]);
}

// Slowest variant
$some_arr = array('a', 'b', 'c', 'd', 'e');
for (
$i = 0; $i < count($some_arr); $i++) {
 print
$some_arr[$i] . "\n";
 unset(
$some_arr[$i]);
}
?>
http://badluck.tv
24-Mar-2008 01:05
Nested For Loop with the same iterator as the parent.
(Well formatted so the resulting code is clean when executed).
Useful for outputting a data array into a table, ie. images.

<?php
//Dummy data
$data = array(73,74,75,76,78,79,80,81,82,83,84,85,86,87);

//Our 'stepping' variable
$g = 0;

//Our rowcount
$rowcount = 0;

echo
"<table cellspacing='0'>\r";
    for (
$i=0; $i<count($data); ) {

       
$rowcount++;
        echo
"    <tr>\r"; //New row

       
$g = $i + 3; //Set our nested limit
       
for( ; $i<$g; $i++) { //nested for loop

           
if (!isset($data[$i])) { //Allow us to break on incomplete rows
               
break;
            }

            echo
"        <td style='border: 1px #000 solid;'>\r"; //Out put a cell
           
echo "            <p>Row $rowcount <br/> Cell: $i <br/> Data: $data[$i]</p>\r";
            echo
"        </td>\r";
        }

        echo
"    </tr> \r"; //End New Row
   
}

echo
"</table>\r";?>
Lawrence
21-Feb-2008 04:46
PHP does not support a 'redo' statement that is common in other languages (such as Perl). However, PHP does not throw an error if it encounters the bareword 'redo'. The following code executes without an error and without 'redoing' anything:

    for ($i = 0; $i < 3; $i++) {
        print "I: $i\n";
       
        if ($count++ < 2) {
            print "  count: $count\n";
            redo;
        }
       
        print "  past redo\n";
    }

In Perl, this would output:

    I: 0
      count: 1
    I: 0
      count: 2
    I: 0
      past redo
    I: 1
      past redo
    I: 2
      past redo

In PHP, this outputs:

    I: 0
      count: 1
      past redo
    I: 1
      count: 2
      past redo
    I: 2
      past redo

PHP sees the 'redo;' line as an unquoted string and silently passes over it with no error (unless you have E_ALL error reporting turned on).

To get a close approximation to a 'redo' statement, you have to replace the redo with something like

    $i--; continue;

as in:

    for ($i = 0; $i < 3; $i++) {
        print "I: $i\n";
       
        if ($count++ < 2) {
            print "  count: $count\n";
            $i--; continue;
        }
       
        print "  past redo\n";
    }

The '$i--;' part has to reverse the effects of the third part of the for statement -- in this case the '$i++' -- as the third part will still be executed in PHP.

Note also that the test part of the for statement will also be reevaluated (unlike a proper 'redo' which doesn't), so any side-effects in that part of the for statement will also be applied.
jdstraughan at gmail dot com
15-Sep-2007 02:49
Make date drop down in form default to today's date:

<html><body><form>

<?php

$dateMMs
= date("m");
$dateDDs = date("d");
$dateYYs = date("Y");
//$date = $dateYYs.'-'.$dateMMs.'-'.$dateDDs;

//Make dateMM Dropdown
echo '<select name="dateMM">';
for (
$i=01; $i<=12; $i++) {
   
$sel = '';
    if (
$dateMMs == $i) {$sel=' selected ';}
    echo
'<option value="'.$i.'" '.$sel.' >'.$i.'</option>';
    }
echo
'</select>';

echo
'/';

//Make dateDD Dropdown
echo '<select name="dateDD">';
for (
$i=1; $i<=31; $i++) {
   
$sel = '';
    if (
$dateDDs == $i) {$sel=' selected ';}
    echo
'<option value="'.$i.'" '.$sel.' >'.$i.'</option>';
    }
echo
'</select>';

echo
'/';

//Make dateYY Dropdown
echo '<select name="dateYY">';
for (
$i=2007; $i<=2010; $i++) {
   
$sel = '';
    if (
$dateYYs == $i) {$sel=' selected ';}
    echo
'<option value="'.$i.'" '.$sel.' >'.$i.'</option>';
    }
echo
'</select>';

?>

</form></body></html>
david dot sledge at yahoo dot com
13-Sep-2007 10:11
In response to mused.biz's comment:

> Incrementing two variables together can also be achieved, eg:
>
> for ($j = "a", $k = "1"; $j <= "f", $k <= "6" ; $j++, $k++)

Note that the statement:

    $j <= "f"

has absolutely no effect on this loop (which isn't to say it doesn't get evaluated), because it is separated from the following statement by a comma.  If $j were to exceed the value "f" before $k exceeded "6", the loop would still continue.

However, the statement:

<?php

for ( $i = 0; $i++, $i < 10; $i++ )
    echo
$i . '<br/>';

?>

will result in the following:

1
3
5
7
9

because $i is incremented before the condition is evaluated, in addition to it being incremented after the completion of each loop.
eduardofleury at uol dot com dot br
14-Jun-2007 01:18
<?php
//this is a different way to use the 'for'
//Essa é uma maneira diferente de usar o 'for'
for($i = $x = $z = 1; $i <= 10;$i++,$x+=2,$z=&$p){
   
   
$p = $i + $x;
   
    print
"\$i = $i , \$x = $x , \$z = $z <br />";
   
}

?>
mused.biz
31-Dec-2006 12:45
Incrementing two variables together can also be achieved, eg:

for ($j = "a", $k = "1"; $j <= "f", $k <= "6" ; $j++, $k++)
mark at rugbyweb dot org
16-Sep-2006 01:42
This is a handy little script for alternating row colours.
<?php
$color1
="#FFFFCC"; //First Colour
$color2="none"; // Second Colour
$row_count=0; //Set row_count to 0
while($m=mysql_fetch_array($query)) //SQL query
{
$row_count++;//Counts row_count
$row_color = ($row_count % 2) ? $color1 : $color2; //Gets the colour to be used
print "<tr style='background:{$row_color}'> //Sets the row colour.
}
?>
This very handy and easy to use.
lishevita at yahoo dot co (notcom) .uk
08-Sep-2006 07:33
On the combination problem again...

 It seems to me like it would make more sense to go through systematically. That would take nested for loops, where each number was put through all of it's potentials sequentially.

The following would give you all of the potential combinations of a four-digit decimal combination, printed in a comma delimited format:

for($a=0;$a<10;$a++){
    for($b=0;$b<10;$b++){
          for($c=0;$c<10;$c++){
              for($d=0;$d<10;$d++){
                echo $a.$b.$c.$d.", ";
              }
           }
      }
}

Of course, if you know that the numbers you had used were in a smaller subset, you could just plunk your possible numbers into arrays $a, $b, $c, and $d and then do nested foreach loops as above.

- Elizabeth
frank at booksku dot com
10-Aug-2006 06:15
re: jdtoth:

I'm fairly sure the following gives you exactly the output you're looking for:

$arr = array(12,18,24,36);
foreach($arr as $num)
  foreach($arr as $inner_num)
    foreach($arr as $last_num)
      echo "$num-$inner_num-$last_num\n";
thomas et luegger _dot_ de
17-Jul-2006 07:44
The previous post from Fatalerror is not correct. Variables enjoy no special treatment inside 'for' statements. At least I was not able to reproduce such a behavior. The code below shows, that the value of $a from loop 1 is still valid outside the scope of it's loop. It can be used without further initialisation for loop 2. So 'while' and 'for' loops are just a matter of taste.

<?php
echo ("In loop 1: ");
for (
$a = 0; $a < 3; $a++) echo("$a,");
echo (
"\r\nAfter loop 1:  a = $a");

echo (
"\r\n\r\nIn loop 2: ");
for ( ;
$a++ < 20; )
{
  echo (
"$a,");
  if (
$a==10) break;
}
echo (
"\r\nAfter Loop 2: a = $a");
?>

output:

In loop 1: 0,1,2,
After loop 1: a = 3

In loop 2: 4,5,6,7,8,9,10,
After Loop 2: a = 10

Greetings, Tom
FatalError
28-Dec-2005 07:56
To add to my previous note, I found a big difference between the two statements. With a "while" statement, you can use $a (from my examples) outside the "while" statement. However, with the "for" statement, you can only use $a within the scope of that statement. In other words, you can't use $a after that "for" statement and expect it to still be equal to the same number it was before.
FatalError
28-Dec-2005 05:01
You can also use a "while" loop to get the same results as a "for" statement. These two examples are basically the same thing:

<?php

for ($a = 0; $a < $somevar; $a++) {
   
/* Do something... */
}

?>

<?php

$a
= 0;
while (
$a < $somevar) {
   
/* Do something... */
   
$a++
}

?>
jdtoth -at- gmail dot com
25-Nov-2005 11:35
I was fooling around, trying to figure out the combination to a lock that I couldnt remember the combo to.  I did remember it involved a few numbers, so I wrote the following:

<?php
// ----------------------------------------------------------------------
// output all possible combinations for lock, based on supplied numbers
// ----------------------------------------------------------------------

// suspected combination numbers
$numbers = array (12,18,24,36);

for (
$i=0; $i <= 10000; $i++)
{
   
srand ((double) microtime() * 1000000);
   
$random1 = rand(0,3);
   
   
srand ((double) microtime() * 1000000);
   
$random2 = rand(0,3);
   
   
srand ((double) microtime() * 1000000);
   
$random3 = rand(0,3);
   
   
$results[] = $numbers[$random1].' - '.$numbers[$random2].' - '.$numbers[$random3];
}

// discard duplicates
$results = array_unique($results);

echo
"** Unique Results ".count($results)." ** <br/><br/>";
foreach (
$results as $output) echo $output . "<br />";

?>

What would be the proper way of writing this code?  Obviously my 'brute-force' method of running a random sequence an extreme amount of times does work and yields what i think is the correct number of combinations, but there must be a more efficient method?
Maciek
15-Nov-2005 07:12
in reply to mbvlist about his loop:

<?php

for($i=0; $i < $max; $i++ && print 'increment,')
{
 
do_something();
  echo
" i = $i\n";
}
echo
"finally, i = $i\n";

?>

Your loop works as you observed, because php evaluates the following as expression:
($i++ && print 'increment)

When $i=0, $i++ returns false, so the second part of the expression (print 'increment') is not evaluated, since there is no output. Since $i > 0 returns true, your print will be evaluated and you will see output..
mbvlist at fastmail dot fm
08-Nov-2005 08:37
While fuzzeling around with iterators (trying to find the next and previous item in a list), discovered something odd:

<?php

for($i=0; $i < $max; $i++ && print 'increment,')
{
 
do_something();
  echo
" i = $i\n";
}
echo
"finally, i = $i\n";

?>

If $max is set at 1 (only the first run will occur), it works as I expected:
i = 0
finally, i = 0

But with $max at a higher value (say 2) it works different:
i = 0
increment, i = 1
increment, finally, i = 2

After the loop was finished $i was incremented! As I read right now, this is what should happen. But it doesn't occur in the first case. As I said, I was searching something using an iterator, and after the loop I wanted to know the next value. Because of this 'feature' (a.k.a. bug) that didn't work.
Be warned!
JustinB at harvest dot org
04-Aug-2005 11:23
For those who are having issues with needing to evaluate multiple items in expression two, please note that it cannot be chained like expressions one and three can.  Although many have stated this fact, most have not stated that there is still a way to do this:

<?php
for($i = 0, $x = $nums['x_val'], $n = 15; ($i < 23 && $number != 24); $i++, $x + 5;) {
   
// Do Something with All Those Fun Numbers
}
?>
dre
21-Jul-2005 06:01
In reply to M. Berndt's code sample: recursion is not "always" faster, especially not when you consider how big the stack's getting.

With FAKTOR = 50:
for(): 0.0222418308258
recursion: 0.175624132156

With FAKTOR = 1000:
for(): 0.228713035583
recursion: 0.459243059158
pmv at nipl dot net
04-Jul-2005 07:55
Actually, it seems calling echo inside a for expression is not allowed, at least as of PHP 5.0.4 (built: May 10 2005 09:56:44). Executing the said code results in the following error:

Parse error: parse error, unexpected T_ECHO in /usr/local/iwcdns/webadmin/foo.php on line 2

However, using the print() function seems to work. From this, it seems sensible to think that PHP does not treat echo as a expression. The following will work as expected:

<?php
for ($i = 'a'; $i != "aa"; $i++, print $i);
?>

(Note the use of the character notation 'a', instead of just a. Using the latter works, but is wrong, as explained in section "Why is $foo[bar] wrong?" of the array section of the manual (http://www.php.net/manual/en/language.types.array.php).)

Also, bpgordon's further shortening is not exactly equivalent to mison's examples. In a for loop, the step expression (i.e. the third one) is executed _after_ the body of the loop. Therefore, a more accurate equivalent would be:

<?php
for ($i = 'a'; $i != "aa"; print $i, $i++);
?>

And further shortening this:

<?php
for ($i = 'a'; $i != "aa"; print $i++);
?>
bpgordon at gmail dot com
12-Jun-2005 11:31
Mison's example can be shortened even further:

<?php
for ($i = a; $i!="aa"; $i++, echo $i)
?>
mison
27-May-2005 09:31
In a previous note:

Following moniarde at yahoo dot com 's idea
<?php
for ($i = a; $i!="aa" ; $i++) {
   echo
$i;
}
?>

This can be trimmed slightly further to:

<?php
for ($i = a; $i!="aa" ; $i++) echo $i;
?>
16-Jan-2005 12:57
Following moniarde at yahoo dot com 's idea
<?php
for ($i = a; $i!="aa" ; $i++) {
   echo
$i;
}

?>

will be good.
jphansen at uga dot edu
15-Oct-2004 07:31
as harbater at teamgenesis dot com noted, don't use a comma to separate conditions in expr2. But if you do, the result will be ONLY the last condition being evaluated for the continuation of the loop. So this would iterate infinitely: for(; false, true;); and if you swapped the true and false it would break immediately.

I wouldn't count using a comma completely out of the question, since there may be a rare circumstance where you would only want to break if the last evaluation returns false.
moniarde at yahoo dot com
01-Jun-2004 04:06
As previously mentioned,

<?
for ($i = a; $i <= z; $i++) {
   echo $i
}
?>

will print a -> z, then aa, ba, ca , etc -> yz.  However, doing this:

<?
for ($i = a; ; $i++) {
    echo $i;
    if ($i == "z") {
        break;
    }
}
?>
will print only a->z.  It's simple, but it works.
user at host dot com
19-Apr-2004 10:53
Also acceptable:
  for($letter = ord('a'); $letter <= ord('z'); $letter++)
   print chr($letter);
hayes029 at bama dot ua dot edu
05-Feb-2004 07:16
For the purposes of outputing the alphabet,

<?php
for ($i="A"; $i <= "Z"; $i++) echo "$i<br>";
?>

will actually output A-Z, then begin again with AA, AB, etc. until it finishes with YZ.  Similarly,

<?php
for ($i="A"; $i <= "ZZ"; $i++) echo "$i<br>";
?>

will output A-Z, AA, AB... ZZ, then begin again with AAA, AAB, AAC... up to ZYZ.

Thus an alternative to timrosseel's example for outputting the alphabet is:

<?php
for ($i="A"; $i != "AA"; $i++) echo "$i<br>";
?>
php at project2501 dot plus dot com
15-Sep-2003 11:45
just to clarify that you can 'chain' expr1, expr2 and expr3, for instance:

<?
for($i=0 , $j=10 ; $i<5 ; $i++ , $j+=5, $k=($i+$j))
{
    echo "i: $i<br />j: $j<br />k: $k<br /><br />";
}
?>

produces:

i: 0
j: 10
k:

i: 1
j: 15
k: 16

i: 2
j: 20
k: 22

i: 3
j: 25
k: 28

i: 4
j: 30
k: 34

in case you need to do more than one operation per iteration.

The reason $k does not start with a value of 10, is because expr3 ($k=($i+$j)) is evaluated at the -end- of each iteration.
bishop
17-Jul-2003 08:23
If you're already using the fastest algorithms you can find (on the order of O(1), O(n), or O(n log n)), and you're still worried about loop speed, unroll your loops using e.g., Duff's Device:

<?php
$n
= $ITERATIONS % 8;
while (
$n--) $val++;
$n = (int)($ITERATIONS / 8);
while (
$n--) {
   
$val++;
   
$val++;
   
$val++;
   
$val++;
   
$val++;
   
$val++;
   
$val++;
   
$val++;
}
?>

(This is a modified form of Duff's original device, because PHP doesn't understand the original's egregious syntax.)

That's algorithmically equivalent to the common form:

<?php
for ($i = 0; $i < $ITERATIONS; $i++) {
   
$val++;
}
?>

$val++ can be whatever operation you need to perform ITERATIONS number of times.

On my box, with no users, average run time across 100 samples with ITERATIONS = 10000000 (10 million) is:
Duff version:       7.9857 s
Obvious version: 27.608 s
thewhiteness at hotmail dot com
16-Dec-2002 10:10
Regarding ben's note: The reason for this is that your first example uses neither the $i++ or $i+= operators. It's like telling PHP to add nothing to it ($i+).

Another way to possibly speed a for loop would be this:

...
for (;condition;) {
// your statement/block here
}
...

This way, if you have a variable that is being updated in the body of the loop anyways, you can use it, rather than specify a number of iterations.
nzamani at cyberworldz dot de
18-Jun-2001 06:47
The point about the speed in loops is, that the middle and the last expression are executed EVERY time it loops.
So you should try to take everything that doesn't change out of the loop.
Often you use a function to check the maximum of times it should loop. Like here:

for ($i = 0; $i <= somewhat_calcMax(); $i++) {
  somewhat_doSomethingWith($i);
}

Faster would be:

$maxI = somewhat_calcMax();
for ($i = 0; $i <= $maxI; $i++) {
  somewhat_doSomethingWith($i);
}

And here a little trick:

$maxI = somewhat_calcMax();
for ($i = 0; $i <= $maxI; somewhat_doSomethingWith($i++)) ;

The $i gets changed after the copy for the function (post-increment).

I don't know if

for ($i = 0; $i <= $maxI; somewhat_doSomethingWith($i), $i++) ;

is correct...at least it's not really clear.
harbater at teamgenesis dot com
27-Mar-2001 02:55
If you want two conditions to be evaluated in expr2, you can't just separate them with commas like you can with expr1 and expr3.

For example, this does not work:
for ($i=$start, $count=0; $i<$total, $count<10; $i+=10, $count++)

But this does:
for ($i=$start, $count=0; ($i<$total && $count<10); $i+=10, $count++)

foreach> <do-while
Last updated: Fri, 23 Jan 2009
 
 
show source | credits | stats | sitemap | contact | advertising | mirror sites