[ Team LiB ] Previous Section Next Section

More About Arguments

You've already seen how to pass arguments to functions, but there's more to cover yet. In this section, you'll look at a technique for giving your arguments default values and explore a method of passing variables by reference rather than by value. This means that the function is given an alias to the original value rather than a copy of it.

Setting Default Values for Arguments

PHP gives you a nifty feature to help build flexible functions. Until now, we've said that some functions demand one or more arguments. By making some arguments optional, you can render your functions a little less autocratic.

Listing 6.11 creates a useful little function that wraps a string in an HTML heading element. We want to give the user of the function the chance to change the heading element's size, so we demand a $size argument in addition to the string (line 10). If the client code provides a $size argument of 1, the string provided in $txt is wrapped in an h1 element and printed. If $size is 2, the string is wrapped in an h2 element, and so on.

Listing 6.11 A Function Requiring Two Arguments
 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.11</title>
 7: </head>
 8: <body>
 9: <?php
10: function headingWrap( $txt, $size ) {
11:     print "<h$size>$txt</h$size>";
12: }
13: headingWrap("Book title", 1);
14: headingWrap("Chapter title",2);
15: headingWrap("Section heading",3);
16: ?>
17: </body>
18: </html>

You can see the output from the script in Listing 6.11 in Figure 6.6. Useful though this function is, we really only need to change the heading size occasionally. Most of the time we would like to default to outputting an h3 element. By assigning a value to an argument variable within the function definition's parentheses, we can make the $size argument optional. If the function call doesn't define an argument for this, the value we have assigned to the argument is used instead. Listing 6.12 uses this technique to make the $size argument optional.

Figure 6.6. A function that formats and outputs strings.

graphics/06fig06.gif

Listing 6.12 A Function with an Optional Argument
 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.11</title>
 7: </head>
 8: <body>
 9: <?php
10: function headingWrap( $txt, $size=3 ) {
11:   print "<h$size>$txt</h$size>";
12: }
13: headingWrap("Book title", 1);
14: headingWrap("Chapter title",2);
15: headingWrap("Section heading");
16: headingWrap("Another Section heading");
17: ?>
18: </body>
19: </html>

When the headingWrap() function is called with a second argument, as in line 13, this value is used to generate the heading element. When we omit this argument, as in lines 15 and 16, the default value of 3 is used instead. You can create as many optional arguments as you want, but when you've given an argument a default value, all subsequent arguments should also be given defaults.

Passing References to Variables to Functions

When you pass arguments to functions, they are stored as copies in parameter variables. Any changes made to these variables in the body of the function are local to that function and are not reflected beyond it. This is illustrated in Listing 6.13.

Listing 6.13 Passing an Argument to a Function by Value
 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.13</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: function addFive( $num ) {
12:   $num += 5;
13: }
14: $orignum = 10;
15: addFive( $orignum );
16: print( $orignum );
17: ?>
18: </div>
19: </body>
20: </html>

The addFive() function accepts a single numeric value and adds 5 to it. It returns nothing. We assign a value to a variable $orignum in line 14 and then pass this variable to addFive() in line 15. A copy of the contents of $orignum is stored in the variable $num. Although we increment $num by 5, this has no effect on the value of $orignum. When we print $orignum, we find that its value is still 10. By default, variables passed to functions are passed by value—in other words, local copies of the values of the variables are made.

We can change this behavior by creating a reference to our original variable. You can think of a reference as a signpost that points to a variable. In working with the reference, you are manipulating the value to which it points.

Listing 6.14 shows this technique in action. When you pass an argument to a function by reference, as in line 15, the contents of the variable you pass ($orignum) are accessed by the argument variable and manipulated within the function, rather than just a copy of the variable's value (10). Any changes made to an argument in these cases change the value of the original variable. You can pass an argument by reference by adding an ampersand to the argument name in the function definition, as shown in line 11.

Listing 6.14 Using a Function Definition to Pass an Argument to a Function by Reference
 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.14</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: function addFive( &$num ) {
12:   $num += 5;
13: }
14: $orignum = 10;
15: addFive( $orignum );
16: print( $orignum );
17: ?>
18: </div>
19: </body>
20: </html>

graphics/watchout_icon.gif

Until recently, it was also usual to set up pass by reference from within the calling code rather than at the function declaration. This technique is referred to as call-time pass-by-reference and involves prepending an ampersand to the variable in the function call rather than in the function declaration. This technique has been deprecated and so should not be used.

If you are using library code that falls foul of this deprecation, you can temporarily suppress PHP's warning messages by setting the allow_call_time_pass_reference directive to on in your php.ini file.


Returning References from Functions

Functions return by value. So, if you pass a variable to a function by reference and then return that variable to the calling code, you return a copy of the variable's value. You do not, by default, return a variable reference. You can change this behavior by prepending an ampersand to the name of your function, like so:


function &addFive( &$num ) {
  $num+=5;
  return $num;
}

$num is now both passed to addFive() and returned from it by reference. We can illustrate this by calling addFive():


$orignum = 10;
$retnum = & addFive( $orignum );
$orignum += 10;
print( $retnum ); // prints 25

In this fragment we assign the result of calling addFive() to another variable, $retnum. Notice that we place an ampersand before the function call to enforce assignment by reference. Now when we add 10 to $orignum, the change is reflected in $retnum. Both $orignum and $retnum now alias one another.

    [ Team LiB ] Previous Section Next Section