[ Team LiB ] Previous Section Next Section

Loops

So far we've looked at decisions a script can make about which code to execute. Scripts can also decide how many times to execute a block of code. Loop statements enable you to achieve repetitive tasks. Almost without exception, a loop continues to operate until either a condition is achieved or you explicitly choose to exit the loop.

The while Statement

The while statement looks similar in structure to a basic if statement:


while ( expression ) {
   // do something
}

As long as a while statement's expression evaluates to true, the code block is executed repeatedly. Each execution of the code block in a loop is often 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.

Listing 5.6 A while Statement
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 5.6 A while Statement</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $counter = 1;
12: while ( $counter <= 12 ) {
13:   print "$counter times 2 is ".($counter*2)."<br />";
14:   $counter++;
15: }
16: ?>
17: </div>
18: </body>
19: </html>

In this example, we initialize a variable called $counter in line 11. The while statement in line 12 tests the $counter variable. As long as the integer contained by $counter is smaller 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 2, and the result is printed to the browser. $counter is incremented in line 14. This last stage is extremely important: If you were to forget to change $counter, the while expression would never resolve to false and the loop would never end.

The do...while Statement

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, like so:


do  {
   // code to be executed
} while (expression);

graphics/bytheway_icon.gif

The test expression of a do...while statement should always end with a semicolon.


This statement might be useful if 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 in which the code block is executed a minimum of one time.

Listing 5.7 The do...while Statement
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 5.7 The do...while Statement</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $num = 1;
12: do {
13:   print "Execution number: $num<br />\n";
14:   $num++;
15: } while ( $num > 200 && $num < 400 );
16: ?>
17: </div>
18: </body>
19: </html>

The do...while statement tests whether the variable $num contains a value that is greater than 200 and smaller than 400. In line 11, 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 prints a single line to the browser.

The for Statement

You cannot achieve anything with a for statement that you could not also manage with a while statement. On the other hand, the 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, and the variable was incremented within the code block. The for statement enables you to achieve this on a single line, making your code more compact and making it less likely that you'll forget to increment a counter variable, thereby creating an infinite loop. Here's its syntax:


for ( initialization expression; test expression; modification expression ) {
  // code to be executed
}

Each expression within the parentheses of the for statement is separated by a semicolon. 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.

Listing 5.8 Using the for Statement
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 5.8 Using the for Statement</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: for ( $counter=1; $counter<=12; $counter++ ) {
12: print "$counter times 2 is".($counter*2)."<br />";
13: }
14: ?>
15: </div>
16: </body>
17: </html>

The results of Listings 5.6 and 5.8 are exactly the same. The for statement, though, makes the code more compact. Because $counter is initialized and incremented at the top of the statement, the logic of the loop is clear at a glance. In line 11, within the for statement's parentheses, the first expression initializes the $counter variable and sets it to 1. The test expression checks that $counter contains a value that is less than or equal to 12; then 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 evaluated again. This process continues until the test expression evaluates to false.

Breaking Out of Loops with the break Statement

Both while and for statements incorporate a built-in test expression with which you can end a loop. The break statement, though, enables you to break out of a loop according to 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.

Listing 5.9 A for Loop That Divides 4000 by Ten Incremental Numbers
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 5.9 A for Loop That Divides Ten Numbers</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: for ( $counter=1; $counter <= 10; $counter++ ) {
12:   $temp = 4000/$counter;
13:   print "4000 divided by $counter is.. $temp<br />";
14: }
15: ?>
16: </div>
17: </body>
18: </html>

In line 11, this example initializes the variable $counter to 1. The for statement's test expression checks that $counter is smaller than or equal to 10. Within the code block, 4000 is divided by $counter, printing the result to the browser.

This seems straightforward enough. But what if the value you place in $counter comes from user input? The value could be a minus 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 as the code block is executed for the fifth time, which is not advisable. Listing 5.10 guards against this by breaking out of the loop if the $counter variable contains 0.

Listing 5.10 Using the break Statement
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 5.10 Using the break Statement</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $counter = -4;
12: for ( ; $counter <= 10; $counter++ ) {
13:   if ( $counter == 0 ) {
14:     break;
15:   }
16:   $temp = 4000/$counter;
17:   print "4000 divided by $counter is.. $temp<br />";
18: }
19: ?>
20: </div>
21: </body>
22: </html>

graphics/bytheway_icon.gif

Dividing a number by zero does not cause a fatal error in PHP. Instead, a warning is generated and execution continues.


We use an if statement, shown in line 13, to test the value of $counter. If it is equivalent to zero, the break statement immediately halts execution of the code block and program flow continues after the for statement.

Notice that we initialized the $counter variable in line 11, outside the for statement's parentheses, to simulate a situation in which the value of $counter is set according to form input or a database lookup.

graphics/didyouknow_icon.gif

You can omit any of the expressions of a for statement, but you must remember to retain the semicolons.


Skipping an Iteration with the continue Statement

The continue statement ends execution of the current iteration but doesn't cause the loop as a whole to end. Instead, the next iteration is immediately begun. Using the break statement 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.

Listing 5.11 Using the continue Statement
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 5.11 Using the continue Statement</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $counter = -4;
12: for ( ; $counter <= 10; $counter++ ) {
13:   if ( $counter == 0 ) {
14:     continue;
15:   }
16:   $temp = 4000/$counter;
17:   print "4000 divided by $counter is .. $temp<br />";
18: }
19: ?>
20: </div>
21: </body>
22: </html>

In line 14, 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 immediately is started.

graphics/watchout_icon.gif

The break and continue statements can make code more difficult to read. Because they often add layers of complexity to the logic of the loop statements that contain them, they are best used with care.


Nesting Loops

Loop statements can contain other loop statements. This combination 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.

Listing 5.12 Nesting Two for Loops
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 5.12 Nesting Two for Loops</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: print "<table border=\"1\">\n";
12: for ( $y=1; $y<=12; $y++ ) {
13:   print "<tr>\n";
14:   for ( $x=1; $x<=12; $x++ ) {
15:     print "\t<td>";
16:     print ($x*$y);
17:     print "</td>\n";
18: }
19: print "</tr>\n";
20: }
21: print "</table>";
22: ?>
23: </div>
24: </body>
25: </html>

Before we examine the for loops, let's take a closer look at line 11 in Listing 5.12:


print "<table border=\"1\">\n";

Notice that we have used the backslash character (\) before each of the quotation marks within the string. This is necessary to tell the PHP engine we want to quote the quotation 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, consisting as it would of a string followed by a number followed by another string. This would generate an error. You will encounter this backslash technique, known as escaping, again in Hour 7, "Arrays."

The outer for statement (line 12) initializes a variable called $y, setting its starting value to 1. It defines an expression that tests whether $y is smaller or equal to 12 and defines the increment for $y. For each iteration, the code block prints a TR (table row) HTML element (line 13) and defines another for statement (line 14). 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 15), as well as the result of $x multiplied by $y (line 16). In line 17, we close the table cell. After the inner loop has completed, we fall back through to the outer loop where we close the table row on line 19, 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 21.

    [ Team LiB ] Previous Section Next Section