So far we've looked at decisions that a script can make about what code to execute. Scripts can also decide how many times to execute a block of code. Loop statements are designed to enable you to achieve repetitive tasks. A loop will continue to operate until a condition is achieved, or you explicitly choose to exit the loop.
The while statement looks similar in structure to a basic if statement:
while (expression ) { // do something }
However, unlike an if statement, a while statement will execute for as long as the expression evaluates to true, over and over again if need be. Each execution of a code block within a loop is called an
iteration . Within the block, you usually change something that affects the while statement's expression; otherwise, your loop continues indefinitely. Listing 5.6 creates a while loop that calculates and prints multiples of 2 up to 24.
1: <l> 2: <head> 3: <title>Listing 5.6</title> 4: </head> 5: <body> 6: <?php 7: $counter = 1; 8: while ($counter <= 12) { 9: echo "$counter times 2 is ".($counter * 2)."<br>"; 10: $counter++; 11: } 12: ?> 13: </body> 14: <l>
In this example, we initialize a variable $counter in line 7. The while statement in line 8 tests the $counter variable. As long as the integer that $counter contains is less than or equal to 12, the loop continues to run. Within the while statement's code block, the value contained by $counter is multiplied by two and the result is printed to the browser. Next, the value of $counter is incremented in line 10. This last stage is extremely important. If you were to forget to change the value assigned to the $counter variable, the while expression would never resolve to false, and the loop would never end.
Put these lines into a text file called testwhile.php, and place this file in your Web server document root. When you access this script through your Web browser, it produces the following:
1 times 2 is 2 2 times 2 is 4 3 times 2 is 6 4 times 2 is 8 5 times 2 is 10 6 times 2 is 12 7 times 2 is 14 8 times 2 is 16 9 times 2 is 18 10 times 2 is 20 11 times 2 is 22 12 times 2 is 24
A do...while statement looks a little like a while statement turned on its head. The essential difference between the two is that the code block is executed before the truth test and not after it:
do { // code to be executed } while (expression );
The test expression of a do...while statement should always end with a semicolon. |
This type of statement is useful when you want the code block to be executed at least once, even if the while expression evaluates to false. Listing 5.7 creates a do...while statement. The code block is executed a minimum of one time.
1: <l> 2: <head> 3: <title>Listing 5.7</title> 4: </head> 5: <body> 6: <?php 7: $num = 1; 8: do { 9: echo "The number is: $num<br>\n"; 10: $num++; 11: } while (($num > 200) && ($num < 400)); 12: ?> 13: </body> 14: <l>
The do...while statement tests whether the variable $num contains a value that is greater than 200 and less than 400. In line 7, we have initialized $num to 1, so this expression returns false. Nonetheless, the code block is executed before the expression is evaluated, so the statement will print a single line to the browser.
Put these lines into a text file called testdowhile.php, and place this file in your Web server document root. When you access this script through your Web browser, it produces the following:
The number is: 1
If you change the value of $num in line 7 to something like 300 and then run the script, the loop will display
The number is: 300
and will continue to print similar lines, with increasing numbers, through
The number is: 399
Anything you want to do with a for statement, you can also do with a while statement, but a for statement is often a neater and safer way of achieving the same effect. Earlier, Listing 5.6 initialized a variable outside the while statement. The while statement then tested the variable in its expression. The variable was incremented within the code block. The for statement allows you to achieve this on a single line. This allows for more compact code and makes it less likely that you will forget to increment a counter variable, thereby creating an infinite loop:
for (initialization expression; test expression; modification expression ) { // code to be executed }
Infinite loops are, as the name suggests, loops that run without bounds. If your loop is running infinitely, your script is running for an infinite amount of time. This is very stressful on your Web server, and renders the Web page in question unusable. |
The expressions within the parentheses of the for statement are separated by semicolons. Usually, the first expression initializes a counter variable, the second expression is the test condition for the loop, and the third expression increments the counter. Listing 5.8 shows a for statement that re-creates the example in Listing 5.6, which multiplies 12 numbers by 2.
1: <l> 2: <head> 3: <title>Listing 5.8</title> 4: </head> 5: <body> 6: <?php 7: for ($counter=1; $counter<=12; $counter++) { 8: echo "$counter times 2 is ".($counter * 2)."<br>"; 9: } 10: ?> 11: </body> 12: <l>
Put these lines into a text file called testfor.php, and place this file in your Web server document root. When you access this script through your Web browser, it produces the following:
1 times 2 is 2 2 times 2 is 4 3 times 2 is 6 4 times 2 is 8 5 times 2 is 10 6 times 2 is 12 7 times 2 is 14 8 times 2 is 16 9 times 2 is 18 10 times 2 is 20 11 times 2 is 22 12 times 2 is 24
The results of Listings 5.6 and 5.8 are exactly the same, but the for statement makes the code in Listing 5.8 more compact. Because the $counter variable is initialized and incremented at the beginning of the statement, the logic of the loop is clear at a glance. In line 7, the first expression initializes the $counter variable and sets it to 1. The test expression verifies that $counter contains a value that is less than or equal to 12. The final expression increments the $counter variable.
When program flow reaches the for loop, the $counter variable is initialized, and the test expression is evaluated. If the expression evaluates to true, the code block is executed. The $counter variable is then incremented and the test expression is evaluated again. This process continues until the test expression evaluates to false.
Both while and for statements incorporate a built-in test expression with which you can end a loop. However, the break statement enables you to break out of a loop based on the results of additional tests. This can provide a safeguard against error. Listing 5.9 creates a simple for statement that divides a large number by a variable that is incremented, printing the result to the screen.
1: <l> 2: <head> 3: <title>Listing 5.9</title> 4: </head> 5: <body> 6: <?php 7: for ($counter=1; $counter <= 10; $counter++) { 8: $temp = 4000/$counter; 9: echo "4000 divided by $counter is... $temp<br>"; 10: } 11: ?> 12: </body> 13: <l>
In line 7, this example initializes the variable $counter to 1. The for statement's test expression verifies that $counter is less than or equal to 10. Within the code block, 4000 is divided by $counter, printing the result to the browser.
Put these lines into a text file called testfor2.php, and place this file in your Web server document root. When you access this script through your Web browser, it produces the following:
4000 divided by 1 is... 4000 4000 divided by 2 is... 2000 4000 divided by 3 is... 1333.33333333 4000 divided by 4 is... 1000 4000 divided by 5 is... 800 4000 divided by 6 is... 666.666666667 4000 divided by 7 is... 571.428571429 4000 divided by 8 is... 500 4000 divided by 9 is... 444.444444444 4000 divided by 10 is... 400
This seems straightforward enough. But what if the value you place in $counter comes from user input? The value could be a negative number, or even a string. Let's take the first instance. Changing the initial value of $counter from 1 to -4 causes 4000 to be divided by 0 when the code block is executed for the fifth time. It is generally not a good idea for your code to divide by zero, as it results in an answer of "undefined." Listing 5.10 guards against this by breaking out of the loop if the $counter variable equals zero.
1: <l> 2: <head> 3: <title>Listing 5.10</title> 4: </head> 5: <body> 6: <?php 7: $counter = -4; 8: for (; $counter <= 10; $counter++) { 9: if ($counter == 0) { 10: break; 11: } else { 12: $temp = 4000/$counter; 13: echo "4000 divided by $counter is... $temp<br>"; 14: } 15: } 16 ?> 17: </body> 18: <l>
Dividing a number by zero does not cause a fatal error in PHP. Instead, PHP generates a warning and execution continues. |
We use an if statement, shown in line 9, to test the value of $counter. If it is equal to zero, the break statement immediately halts execution of the code block, and program flow continues after the for statement (line 16).
Put these lines into a text file called testfor3.php, and place this file in your Web server document root. When you access this script through your Web browser, it produces the following:
4000 divided by -4 is... -1000 4000 divided by -3 is... -1333.33333333 4000 divided by -2 is... -2000 4000 divided by -1 is... -4000
Notice that we initialize the $counter variable in line 7, outside the for statement's parentheses, to simulate a situation in which the value of $counter is set from outside the script.
You can omit any of the expressions from a for statement, but you must remember to retain the semicolons.
The continue statement ends execution of the current iteration but doesn't cause the loop as a whole to end. Instead, the next iteration begins immediately. Using the break statement as we did in Listing 5.10 is a little drastic. With the continue statement in Listing 5.11, you can avoid a divide by zero error without ending the loop completely.
1: <l> 2: <head> 3: <title>Listing 5.11</title> 4: </head> 5: <body> 6: <?php 7: $counter = -4; 8: for (; $counter <= 10; $counter++) { 9: if ($counter == 0) { 10: continue; 11: } 12: $temp = 4000/$counter; 13: echo "4000 divided by $counter is... $temp<br>"; 14: } 15: ?> 16: </body> 17: <l>
In line 10, we have swapped the break statement for a continue statement. If the $counter variable is equivalent to zero, the iteration is skipped and the next one starts immediately.
Put these lines into a text file called testcontinue.php, and place this file in your Web server document root. When you access this script through your Web browser, it produces the following:
4000 divided by -4 is... -1000 4000 divided by -3 is... -1333.33333333 4000 divided by -2 is... -2000 4000 divided by -1 is... -4000 4000 divided by 1 is... 4000 4000 divided by 2 is... 2000 4000 divided by 3 is... 1333.33333333 4000 divided by 4 is... 1000 4000 divided by 5 is... 800 4000 divided by 6 is... 666.666666667 4000 divided by 7 is... 571.428571429 4000 divided by 8 is... 500 4000 divided by 9 is... 444.444444444
Loop statements can contain other loop statements. The combination of such statements is particularly useful when working with dynamically created HTML tables. Listing 5.12 uses two for statements to print a multiplication table to the browser.
1: <l> 2: <head> 3: <title>Listing 5.12</title> 4: </head> 5: <body> 6: <?php 7: echo "<table border=\"1\"> \n"; 8: for ($y=1; $y<=12; $y++) { 9: echo "<tr> \n"; 10: for ($x=1; $x<=12; $x++) { 11: echo "<td>"; 12: echo ($x * $y); 13: echo "</td> \n"; 14: } 15: echo "</tr> \n"; 16: } 17: echo "</table>"; 18: ?> 19: </body> 20: <l>
Before we examine the for loops, let's take a closer look at line 7 in Listing 5.12:
echo "<table border=\"1\"> \n";
Notice that we have used the backslash character (\) before each of the quotation marks within the string. This is necessary in order to tell the PHP engine that we wish to use the quotation mark character, rather than interpret it as the beginning or end of a string. If we did not do this, the statement would not make sense to the engine, which would read it as a string followed by a number followed by another string. This would generate an error. In this listing, we also use \n to represent a newline character.
The outer for statement (line 8) initializes a variable called $y, setting its starting value to 1. It defines an expression that verifies that $y is less than or equal to 12 and defines the increment for $y. For each iteration, the code block prints a tr (table row) HTML element (line 9) and defines another for statement (line 10). This inner loop initializes a variable called $x and defines expressions along the same lines as for the outer loop. For each iteration, the inner loop prints a td (table cell) element to the browser (line 11), as well as the result of $x multiplied by $y (line 12). In line 13, we close the table cell. After the inner loop has finished, we fall back through to the outer loop, where we close the table row on line 15, ready for the process to begin again. When the outer loop has finished, the result is a neatly formatted multiplication table. We wrap things up by closing the table on line 17.
Put these lines into a text file called testnestfor.php, and place this file in your Web server document root. When you access this script through your Web browser, it should look like Figure 5.1.