[ Team LiB ] Previous Section Next Section

Saving State Between Function Calls with the static Statement

Variables within functions have a short but happy life on the whole. They come into being when the function is called and die when execution is finished. This is as it should be. It is usually best to build a script as a series of self-contained blocks, each with as little knowledge of others as possible. Occasionally, however, you might want to give a function a rudimentary memory.

Let's assume we want a function to keep track of the number of times it has been called. Why? In our examples, the function is designed to create numbered headings in a script that dynamically builds online documentation.

We could, of course, use our newfound knowledge of the global statement to do this. We have a crack at this in Listing 6.9.

Listing 6.9 Using the global Statement to Remember the Value of a Variable Between Function Calls
 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 6.9 Tracking with the global Statement</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $num_of_calls = 0;
12: function numberedHeading( $txt ) {
13:   global $num_of_calls;
14:   $num_of_calls++;
15:   print "<h1>$num_of_calls. $txt</h1>";
16: }
17: numberedHeading("Widgets");
18: print "<p>We build a fine range of widgets</p>";
19: numberedHeading("Doodads");
20: print "<p>Finest in the world</p>";
21: ?>
22: </div>
23: </body>
24: </html>

This does the job. We declare a variable, $num_of_calls, on line 11, outside the function numberedHeading(). We make this variable available to the function with the global statement on line 13. You can see the output of Listing 6.9 in Figure 6.5.

Figure 6.5. Using the global statement to keep track of the number of times a function has been called.

graphics/06fig05.gif

Every time numberedHeading() is called, $num_of_calls is incremented (line 14). We can then print a heading complete with a heading number.

This is not the most elegant solution, however. Functions that use the global statement cannot be read as standalone blocks of code. In reading or reusing them, you need to look out for the global variables they manipulate.

This is where the static statement can be useful. If you declare a variable within a function in conjunction with the static statement, the variable remains local to the function. On the other hand, the function "remembers" the value of the variable from execution to execution. Listing 6.10 adapts the code from Listing 6.9 to use the static statement.

Listing 6.10 Using the static Statement to Remember the Value of a Variable Between Function Calls
 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 6.10 Using the static Statement</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: function numberedHeading( $txt ) {
12:   static $num_of_calls = 0;
13:   $num_of_calls++;
14:   print "<h1>$num_of_calls. $txt</h1>";
15: }
16: ?>
17: numberedHeading( "Widgets" );
18: print "<p>We build a fine range of widgets</p>";
19: numberedHeading( "Doodads" );
20: print "<p>Finest in the world</p>";
21: </div>
22: </body>
23: </html>

numberedHeading() has become entirely self-contained. When we declare the $num_of_calls variable on line 12, we assign an initial value to it. This assignment is made when the function is first called on line 17. This initial assignment is ignored when the function is called a second time on line 19. Instead, the previous value of $num_of_calls is remembered. We can now paste the numberedHeading() function into other scripts without worrying about global variables. Although the output of Listing 6.10 is exactly the same as that for Listing 6.9, we have made the code more elegant.

    [ Team LiB ] Previous Section Next Section