|
for
for (expr1; expr2; expr3)
The first expression (
In the beginning of each iteration,
At the end of each iteration,
Each of the expressions can be empty or contain multiple
expressions separated by commas. Comma separated expressions in expr2
are treated similarly to being separated by the || operator but has a
lower precedence than ||.
Consider the following examples. All of them display the numbers 1 through 10: <?php
Of course, the first example appears to be the nicest one (or
perhaps the fourth), but you may find that being able to use empty
expressions in
PHP also supports the alternate "colon syntax" for
for (expr1; expr2; expr3): Related Examples ( Source code ) » control_structures.for Examples ( Source code ) » Fill patterns 'Imagick' Examples ( Source code ) » Creating a reflection Examples ( Source code ) » ImagickPixelIterator Examples ( Source code ) » Trimming an image - Imagick Examples ( Source code ) » Analyzing image properties - Imagick Examples ( Source code ) » Creating a simple line graph - ImagickDraw Examples ( Source code ) » Choosing watermark color based on the background luminosity Examples ( Source code ) » Animating GIF images - Imagick Examples ( Source code ) » ImagickDraw, more complex drawing Examples ( Source code ) » ImagickDraw, a quick introduction to drawing Examples ( Source code ) » Creating a PDF preview Examples ( Source code ) » Watermarking made simple -Imagick Examples ( Source code ) » Access a Microsoft WebService in PHP Examples ( Source code ) » Create a PDF document containing a pie chart Examples ( Source code ) » Generate PDFs with PHP Code Examples / Notes » control_structures.forfatalerror
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++ } ?> mbvlist
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! fatalerror
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.
mark
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. thomas et luegger _dot_ de
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 nzamani
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. thewhiteness
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. frank
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"; lishevita
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 bpgordon
Mison's example can be shortened even further: <?php for ($i = a; $i!="aa"; $i++, echo $i) ?> jdstraughan
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> php
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. fb_mathman
It is intersting how to use a structure that can substitue "for". In the next lines, for instance, I create a function that get the smallest free_id for a table. It has good applications for the phpBB forum. <?php function assign_free_id($table, $id_field) { global $db; $sql = "SELECT $id_field FROM $table WHERE 1 ORDER BY $id_field ASC"; if( !$result = $db->sql_query($sql) ) { message_die(GENERAL_ERROR, "Couldn't get id parameters for all the elements of the table", "", __LINE__, __FILE__, $sql); } while ($arr = $db->sql_fetchrow($result)) { $row[]=$arr; } $max_elements = count($row); if ($max_elements==0) { $id= 1; return ($id); } //here I could insert a double-for structure, but I did as it follows, and I think it is more easy to process. //local variable defining.... $i=1; for ( $j=0; $j<$max_elements; $j++) { if ($i==intval($row[$j][0])) { // ...go to next cycle $i++; } else { $id=$i; return $id; } } } ?> mused.biz
Incrementing two variables together can also be achieved, eg: for ($j = "a", $k = "1"; $j <= "f", $k <= "6" ; $j++, $k++) david dot sledge
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. maciek
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.. dre
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 mison
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; ?> bishop
If you're into 1-liners or compact code: <?php implode("\n", range('a','z')); ?> Run-times (on my boxes) are comparable to the other methods using for(). This version is (arguably) more readable than other solutions. 13-nov-2005 11:23
if you wanted to make a next previous thing for mysql this would be it $page = $_GET['page']; // mysql query goes here $limit = 30; //gets 30 of whatever if(!$page){ $page = "1"; } $limitvalue = $page * $limit - ($limit); //find the limit value $query = mysql_query("SELECT * FROM `table`ORDER BY id DESC LIMIT $limitvalue, $limit"); $numrows = mysql_query("SELECT * FROM `forum_topics` WHERE `forumid` = '$fid'"); $numofpages = ceil($numrows / $limit); while ($r = mysql_fetch_array($query)){ // your stuff goes here } $pageprev = $page-1; $pagenext = $page+1; if ($page != "1"){ echo " <a href='linkhere.php?page=$pageprev'><< Previous</a> "; } for ($i = 1; $i <= $numofpages; $i++) { if ($i == $page){ echo "<b>$i</b> "; } else { echo "<a href='linkhere.php?page=$i'>$i</a> "; } } if ($numrows > $limit){ if ($page != $numofpages){ echo " <a href='linkhere.php?page=$pagenext'>Next >></a> "; } } There is also a few other ways but this is how i do it ^^ harbater
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++) jdtoth -at- gmail dot com
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? robert
Here is a quick function I wrote for creating a web-true colour palette. function webTrueColors() { // create array for hexadecimal colors $colors = array("00", "33", "66", "99", "CC", "FF"); // build table $c= "<table cellspacing=0 cellpaddding=0 border=1>"; // loop through all combinations for ($i=0; $i<6; $i++) { for ($j=0; $j<6; $j++) { $c.= "<tr>"; for ($k=0; $k<6; $k++) { $thisColor = $colors[$i].$colors[$j].$colors[$k]; // display color and hex value $c.= "<td bgcolor=\"#".$thisColor."\">".$thisColor."</td>"; } $c.= "</tr>"; } } // close table $c.= "</table>"; // output to screen echo $c; } see_the_address
Here a bit more flexible solution of a task "brutforce" by "jdtoth -at- gmail dot com", and also should be faster ;-) It uses recursion. But it requires quite much memory (especially when playing with $num_positions), I'm not sure it's OK... If anybody has ideas about that - you are welcome: ultraBoy aat mail ddot ru <?php function get_result($len, &$alphabet) { if ($len == 1) { $result = array(); while (list($row_key, $row) = each($alphabet)) { $result[] = array($row); }; } else { $result = get_result($len - 1, $alphabet); reset($result); $new_result = array(); while (list($row_key, $row) = each($result)) { reset($alphabet); while (list($l_key, $l) = each($alphabet)) { $new_row = $row; $new_row[] = $l; $new_result[] = $new_row; }; } $result = $new_result; } return $result; } // suspected combination numbers $numbers = array(12,18,24,36); // how many numbers are in one combunation $num_positions = 3; echo 'Total rows: '.pow(count($numbers), $num_positions).'<br />'; $result = get_result($num_positions, $numbers); foreach ($result as $row_num => $row) { echo "$row_num: "; foreach ($row as $val) { echo $val.' '; } echo '<br />'; } ?> berndt
for(){} versus recursion (always faster) http://www.michael-berndt.de/ie/tux/for_versus_recursion.htm justinb
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 } ?> hayes029
For the purposes of outputing the alphabet, <?php for ($i="A"; $i <= "Z"; $i++) echo "$i "; ?> 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 "; ?> 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 "; ?> 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. moniarde
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. jphansen
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. user
Also acceptable: for($letter = ord('a'); $letter <= ord('z'); $letter++) print chr($letter); pmv
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++); ?> eduardofleury
<?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 />"; } ?> |