Sams Teach Yourself PHP, MySQL and Apache All in One (2012)

Part II. PHP Language Structure

Chapter 7. Working with Functions


In this chapter, you learn the following:

• How to define and call functions from within your scripts

• How to pass values to functions and receive values in return

• How to call a function dynamically using a string stored in a variable

• How to access global variables from within a function

• How to give a function a “memory”

• How to pass data to functions by reference

• How to verify that a function exists before calling it


Functions are at the heart of a well-organized script and make your code easy to read and reuse. No large project would be manageable without them because the problem of repetitive code would bog down the development process. Throughout this chapter, you investigate functions and learn some of the ways functions can save you from repetitive work.

What Is a Function?

You can think of a function as an input/output machine. This machine takes the raw materials you feed it (input) and works with them to produce a product (output). A function accepts values, processes them, and then performs an action (printing to the browser, for example), returns a new value, or both.

If you needed to bake a single cake, you would probably do it yourself, in your own kitchen with your standard oven. But if you needed to bake thousands of cakes, you would probably build or acquire a special cake-baking machine, built for baking cakes in massive quantities. Similarly, when deciding whether to create a function for reuse, the most important factor to consider is the extent to which it can save you from writing repetitive code.

function is a self-contained block of code that can be called by your scripts. When called, the function’s code is executed and performs a particular task. You can pass values to a function, which then uses the values appropriately—storing them, transforming them, displaying them, whatever the function is told to do. When finished, a function can also pass a value back to the original code that called it into action.

Calling Functions

Functions come in two flavors: those built in to the language and those you define yourself. PHP has hundreds of built-in functions. Look at the following snippet for an example of a function in use:

strtoupper("Hello Web!");

This example calls the strtoupper() function, passing it the string "Hello Web!". The function then goes about its business of changing the contents of the string to uppercase letters. A function call consists of the function name (strtoupper in this case) followed by parentheses. If you want to pass information to the function, you place it between these parentheses. A piece of information passed to a function in this way is called an argument. Some functions require that more than one argument be passed to them, separated by commas:

some_function($an_argument, $another_argument);

strtoupper() is typical for a function in that it returns a value. Most functions return some information back after they’ve completed their task; they usually at least tell whether their mission was successful. strtoupper() returns a string value, so its usage requires the presence of a variable to accept the new string, such as the following:

$new_string = strtoupper("Hello Web!");

You may now use $new_string in your code, such as to print it to the screen:

echo $new_string;

This code results in the following text on the screen:

HELLO WEB!


Note

The print() and echo() functions are not actually functions, they’re language constructs designed to output strings to the browser. However, you will find them in the PHP function list, at http://www.php.net/print and http://www.php.net/echo, respectively. These constructs are similar in functionality and can be used interchangably. Whichever one you use is a matter of taste.


The abs() function, for example, requires a signed numeric value and returns the absolute value of that number. Let’s try it out in Listing 7.1.

Listing 7.1 Calling the Built-In abs() Function


1: <?php
2: $num = -321;
3: $newnum = abs($num);
4: echo $newnum;
5: //prints "321"
6: ?>


This example assigns the value -321 to a variable $num. It then passes that variable to the abs() function, which makes the necessary calculation and returns a new value. The code assigns this to the variable $newnum and displays the result.

Put these lines into a text file called abs.php and place this file in your web server document root. When you access this script through your web browser, it produces the following:

321

In fact, Listing 7.1 could have dispensed with temporary variables altogether, passing the number straight to the abs() function and directly printing the result:

echo abs(-321);

This example uses the temporary variables $num and $newnum, though, to make each step of the process as clear as possible. Sometimes you can make your code more readable by breaking it up into a greater number of simple expressions.

You can call user-defined functions in exactly the same way that we have been calling built-in functions.

Defining a Function

You can define your own functions using the function statement:

function some_function($argument1, $argument2)
{
     //function code here
}

The name of the function follows the function statement and precedes a set of parentheses. If your function requires arguments, you must place comma-separated variable names within the parentheses. These variables are filled by the values passed to your function. Even if your function doesn’t require arguments, you must nevertheless supply the parentheses.


Note

The naming rules for functions are similar to the naming rules for variables, which you learned in Chapter 5, “The Building Blocks of PHP.” Names cannot include spaces, and they must begin with a letter or an underscore. As with variables, your function names should be meaningful and consistent in style. The capitalization of function names is one such stylistic touch you can add to your code; using mixed case in names, such as MyFunction() or handleSomeDifficultTask(), makes your code much easier to read. You may hear this naming convention referred to as CamelCase or lower CamelCase, depending on whether the first character is capitalized.


Listing 7.2 declares and calls a function.

Listing 7.2 Declaring and Calling a Function


1: <?php
2: function bighello()
3: {
4:      echo "<h1>HELLO!</h1>";
5: }
6: bighello();
7: ?>


The script in Listing 7.2 simply outputs the string "HELLO!" wrapped in an HTML h1 element.

Put these lines into a text file called bighello.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 7.1.

image

Figure 7.1 Output of bighello.php.

Listing 7.2 declares a function, bighello(), that requires no arguments. Because of this, the parentheses are left empty. Although bighello() is a working function, it is not terribly useful. Listing 7.3 creates a function that requires an argument and actually does something with it.

Listing 7.3 Declaring a Function That Requires an Argument


1: <?php
2: function printBR($txt)
3: {
4:      echo $txt."<br/>";
5: }
6: printBR("This is a line.");
7: printBR("This is a new line.");
8: printBR("This is yet another line.");
9: ?>



Note

Unlike variable names, function names are not case sensitive. In Listing 7.3, the printBR() function could have been called as printbr(), PRINTBR(), or any combination thereof, with success.


Put these lines into a text file called printbr.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 7.2.

image

Figure 7.2 A function that prints a string with an appended <br/> tag.

In line 2, the printBR() function expects a string, so the variable name $txt is placed between the parentheses when the function is declared. Whatever is passed to printBR() is stored in this $txt variable. Within the body of the function, line 3 prints the $txt variable, appending a <br/>element to it.

When you want to print a line to the browser, such as in line 6, 7, or 8, you can call printBR() instead of the built-in print(), saving you the bother of typing the <br/> element.

Returning Values from User-Defined Functions

The previous example output an amended string to the browser within the printBR() function. Sometimes, however, you will want a function to provide a value that you can work with yourself. If your function has transformed a string that you have provided, you might want to get the amended string back so that you can pass it to other functions. A function can return a value using the return statement in conjunction with a value. The return statement stops the execution of the function and sends the value back to the calling code.

Listing 7.4 creates a function that returns the sum of two numbers.

Listing 7.4 A Function That Returns a Value


1: <?php
2: function addNums($firstnum, $secondnum)
3: {
4:      $result = $firstnum + $secondnum;
5:      return $result;
6: }
7: echo addNums(3,5);
8: //will print "8"
9: ?>


Put these lines into a text file called addnums.php and place this file in your web server document root. When you access this script through your web browser, it produces the following:

8

Notice in line 2 that addNums() should be called with two numeric arguments (line 7 shows those to be 3 and 5 in this case). These values are stored in the variables $firstnum and $secondnum. Predictably, addNums() adds the numbers contained in these variables and stores the result in a variable called $result.

The return statement can return a value or nothing at all. How you arrive at a value passed by return can vary. The value can be hard-coded:

return 4;

It can be the result of an expression:

return $a/$b;

It can be the value returned by yet another function call:

return another_function($an_argument);

Variable Scope

A variable declared within a function remains local to that function. In other words, it is not available outside the function or within other functions. In larger projects, this can save you from accidentally overwriting the contents of a variable when you declare two variables with the same name in separate functions.

Listing 7.5 creates a variable within a function and then attempts to print it outside the function.

Listing 7.5 Variable Scope: A Variable Declared Within a Function Is Unavailable Outside the Function


1: <?php
2: function test()
3: {
4:      $testvariable = "this is a test variable";
5: }
6: echo "test variable: ".$testvariable."<br/>";
7: ?>


Put these lines into a text file called scopetest.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 7.3.

image

Figure 7.3 Output of scopetest.php.


Note

The exact output you see depends on your PHP error settings. That is, it might or might not produce a “notice” as shown in Figure 7.3, but it will show the lack of an additional string after “test variable".


The value of the variable $testvariable is not printed because no such variable exists outside the test() function. Remember that the attempt in line 6 to access a nonexistent variable produces a notice such as the one displayed only if your PHP settings are set to display all errors, notices, and warnings. If your error settings are not strictly set, only the string "test variable:" is shown.

Similarly, a variable declared outside a function is not automatically available within it.

Accessing Variables with the global Statement

From within one function, you cannot (by default) access a variable defined in another function or elsewhere in the script. Within a function, if you attempt to use a variable with the same name, you will only set or access a local variable. Let’s put this to the test in Listing 7.6.

Listing 7.6 Variables Defined Outside Functions Are Inaccessible from Within a Function by Default


1: <?php
2: $life = 42;
3: function meaningOfLife()
4: {
5:      echo "The meaning of life is ".$life";
6: }
7: meaningOfLife();
8: ?>


Put these lines into a text file called scopetest2.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 7.4.

image

Figure 7.4 Attempting to reference a variable from outside the scope of a function.

As you might expect, the meaningOfLife() function does not have access to the $life variable in line 2; $life is empty when the function attempts to print it. On the whole, this is a good thing because it saves you from potential clashes between identically named variables, and a function can always demand an argument if it needs information about the outside world. Occasionally, you might want to access an important variable from within a function without passing it in as an argument. This is where the global statement comes into play. Listing 7.7 uses global to restore order to the universe.

Listing 7.7 Accessing Global Variables with the global Statement


1: <?php
2: $life=42;
3: function meaningOfLife()
4: {
5:      global $life;
6:      echo "The meaning of life is ".$life";
7: }
8: meaningOfLife();
9: ?>


Put these lines into a text file called scopetest3.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 7.5.

image

Figure 7.5 Successfully accessing a global variable from within a function using the global statement.

When you place the global statement in front of the $life variable when it is declared in the meaningOfLife() function (line 5), it refers to the $life variable declared outside the function (line 2).

You need to use the global statement within every function that needs to access a particular named global variable. Be careful, though: If you manipulate the contents of the variable within the function, the value of the variable changes for the script as a whole.

You can declare more than one variable at a time with the global statement by simply separating each of the variables you want to access with commas:

global $var1, $var2, $var3;


Caution

Usually, an argument is a copy of whatever value is passed by the calling code; changing it in a function has no effect beyond the function block. Changing a global variable within a function, however, changes the original and not a copy. Use the global statement carefully.


Saving State Between Function Calls with the static Statement

Local variables within functions have a short but happy life—they come into being when the function is called and die when execution is finished, as they should. Occasionally, however, you might want to give a function a rudimentary memory.

Assume that you want a function to keep track of the number of times it has been called so that numbered headings can be created by a script. You could, of course, use the global statement to do this, as shown in Listing 7.8.

Listing 7.8 Using the global Statement to Remember the Value of a Variable Between Function Calls


1:  <?php
2:  $num_of_calls = 0;
3:  function numberedHeading($txt)
4:  {
5:      global $num_of_calls;
6:      $num_of_calls++;
7:      echo "<h1>".$num_of_calls." ".$txt."</h1>";
8:  }
9:  numberedHeading("Widgets");
10: echo "<p>We build a fine range of widgets.</p>";
11: numberedHeading("Doodads");
12: echo "<p>Finest in the world.</p>";
13: ?>


Put these lines into a text file called numberedheading.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 7.6.

image

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

This does the job. Listing 7.8 declares a variable, $num_of_calls, in line 2, outside the function numberedHeading(). Line 5 makes this variable available to the function by using the global statement.

Every time numberedHeading() is called, the value of $num_of_calls is incremented (line 6). You can then print out the heading complete with the properly incremented 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, we need to look out for the global variables that 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, and the function “remembers” the value of the variable from execution to execution. Listing 7.9 adapts the code from Listing 7.8 to use the static statement.

Listing 7.9 Using the static Statement to Remember the Value of a Variable Between Function Calls


1:  <?php
2:  function numberedHeading($txt)
3:  {
4:      static $num_of_calls = 0;
5:      $num_of_calls++;
6:      echo "<h1>".$num_of_calls." ". $txt."</h1>";
7:  }
8:  numberedHeading("Widgets");
9:  echo "<p>We build a fine range of widgets.</p>";
10: numberedHeading("Doodads");
11: echo "<p>Finest in the world.</p>";
12: ?>


The numberedHeading() function has become entirely self-contained. When the $num_of_calls variable is declared on line 4, an initial value is assigned to it. This assignment is made when the function is first called on line 8. This initial assignment is ignored when the function is called a second time on line 10. Instead, the code remembers the previous value of $num_of_calls. You can now paste the numberedHeading() function into other scripts without worrying about global variables. Although the output of Listing 7.9 is the same as that of Listing 7.8, the code is a bit more elegant.

More About Arguments

You’ve already seen how to pass arguments to functions, but there’s plenty more to cover. This section covers a technique for giving your arguments default values and explores a method of passing variables by reference rather than by value. This means that the function is given an alias of the original value rather than a copy of it.

Setting Default Values for Arguments

PHP provides a nifty feature to help build flexible functions. Until now, you’ve heard that some functions require one or more arguments. By making some arguments optional, you can render your functions a little less autocratic.

Listing 7.10 creates a useful little function that wraps a string in an HTML span element. To give the user of the function the chance to change the font-size style, you can demand a $fontsize argument in addition to the string (line 2).

Listing 7.10 A Function Requiring Two Arguments


1:  <?php
2:  function fontWrap($txt, $fontsize)
3:  {
4:     echo "<span style=\"font-size:$fontsize\">".$txt."</span>";
5:  }
6:  fontWrap("A Heading<br/>","24pt");
7:  fontWrap("some body text<br/>","16pt");
8:  fontWrap("smaller body text<br/>","12pt");
9:  fontWrap("even smaller body text<br/>","10pt");
10: ?>


Put these lines into a text file called fontwrap.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 7.7.

image

Figure 7.7 A function that formats and outputs strings.

By assigning a value to an argument variable within the function definition’s parentheses, you can make the $fontsize argument optional. If the function call doesn’t define an argument for this argument, the value you have assigned to the argument is used instead. Listing 7.11 uses this technique to make the $fontsize argument optional.

Listing 7.11 A Function with an Optional Argument


1:  <?php
2:  function fontWrap($txt, $fontsize = "12pt")
3:  {
4:     echo "<span style=\"font-size:$fontsize\">".$txt."</span>";
5:  }
6:  fontWrap("A Heading<br/>","24pt");
7:  fontWrap("some body text<br/>");
8:  fontWrap("smaller body text<br/>");
9:  fontWrap("even smaller body text<br/>");
10: ?>


When the fontWrap() function is called with a second argument, as in line 6, this value is used to set the font-size attribute of the span element. When this argument is omitted, as in lines 7, 8, and 9, the default value of "12pt" 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 Variable References 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, as illustrated in Listing 7.12.

Listing 7.12 Passing an Argument to a Function by Value


1: <?php
2: function addFive($num)
3: {
4:      $num += 5;
5: }
6: $orignum = 10;
7: addFive($orignum);
8: echo $orignum;
9: ?>


Put these lines into a text file called addfive.php and place this file in your web server document root. When you access this script through your web browser, it produces the following:

10

The addFive() function accepts a single numeric value and adds 5 to it, but it returns nothing. A value is assigned to a variable $orignum in line 6 and then this variable is passed to addFive() in line 7. A copy of the contents of $orignum is stored in the variable $num. Although $num is incremented by 5, this has no effect on the value of $orignum. When $orignum is printed, you 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.

You can change this behavior by creating a reference to your 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 7.13 shows this technique in action. When you pass an argument to a function by reference, as in line 7, 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 2.

Listing 7.13 Using a Function Definition to Pass an Argument to a Function by Reference


1: <?php
2: function addFive(&$num)
3: {
4:      $num += 5;
5: }
6: $orignum = 10;
7: addFive($orignum);
8: echo $orignum;
9: ?>


Put these lines into a text file called addfive2.php and place this file in your web server document root. When you access this script through your web browser, it produces the following:

15

Testing for the Existence of a Function

You do not always know that a function exists before you try to invoke it. Different builds of the PHP engine might include different functionality, and if you are writing a script that may be run on multiple servers, you might want to verify that key features are available. For instance, you might want to write code that uses MySQL if MySQL-related functions are available but simply log data to a text file otherwise.

You can use function_exists() to check for the availability of a function. function_exists() requires a string representing a function name. It returns true if the function can be located, and false otherwise.

Listing 7.14 shows function_exists() in action and illustrates some of the other topics we have covered in this chapter.

Listing 7.14 Testing for a Function’s Existence


1:  <?php
2:  function tagWrap($tag, $txt, $func = "")
3:  {
4:      if ((!empty($txt)) && (function_exists($func))) {
5:          $txt = $func($txt);
6:          return "<".$tag.">".$txt."</".$tag."><br/>";
7:      } else {
8:          return "<strong>".$txt."</strong><br/>";
9:      }
10: }
11:
12: function underline($txt)
13: {
14:    return "<span style=\"text-decoration:underline;\">".$txt."</span>";
15: }
16: echo tagWrap('strong', 'make me bold');
17: echo tagWrap('em', 'underline and italicize me', "underline");
18: echo tagWrap('em', 'make me italic and quote me',
19: create_function('$txt', 'return ""$txt"";'));
20: ?>


Listing 7.14 defines two functions, tagWrap() (line 2) and underline() (line 12). The tagWrap() function accepts three strings: a tag, the text to format, and an optional function name. It returns a formatted string. The underline() function requires a single argument—the text to be formatted—and returns the text wrapped in <span> tags with appropriate style attributes.

When you first call tagWrap() on line 16, you pass it the string strong and the string "make me bold". Because you haven’t passed a value for the function argument, the default value (an empty string) is used. Line 4 checks whether the $func variable contains characters, and, if it is not empty,function_exists() is called to check for a function by that name. Of course, in this case, the $func variable is empty, so the $txt variable is wrapped in <strong> tags in the else clause on lines 7 and 8 and the result is returned.

The code calls tagWrap() on line 17 with the string 'em', some text, and a third argument: "underline". function_exists() finds a function called underline() (line 12), so it calls this function and passes the $txt argument variable to it before any further formatting is done. The result is an italicized, underlined string.

Finally, on line 18, the code calls tagWrap(), which wraps text in quotation entities. It is quicker to simply add the entities to the text to be transformed ourselves, but this example serves to illustrate the point that function_exists() works as well on anonymous functions as it does on strings representing function names.

Put these lines into a text file called exists.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 7.8.

image

Figure 7.8 Output of exists.php.

Summary

This chapter taught you about functions and how to deploy them. You learned how to define and pass arguments to a function, how to use the global and static statements, how to pass references to functions, and how to create default values for function arguments. You also learned to test for the existence of functions.

Q&A

Q. Can I include a function call within a double- or single-quoted string, as I can with a variable?

A. No. You must call functions outside quotation marks. However, you can break the string apart and place the function call between the parts of the string, using the concatenation operator to tie them together, as follows:

$newstring = "I purchased".numPurchase($somenum)." items.";

Q. What happens if I call a function that does not exist, or if I declare a function with a name already in use?

A. Calling a function that does not exist or declaring a function with the same name as another existing function causes the script to stop execution. Whether an error message displays in the browser depends on the error settings in your php.ini file.

Workshop

The workshop is designed to help you review what you’ve learned and begin putting your knowledge into practice.

Quiz

1. True or false: If a function doesn’t require an argument, you can omit the parentheses in the function call.

2. How do you return a value from a function?

3. What does the following code fragment print to the browser?

$number = 50;

function tenTimes() {
    $number = $number * 10;
}

tenTimes();
echo $number;

4. What does the following code fragment print to the browser?

$number = 50;

function tenTimes() {
    global $number;
    $number = $number * 10;
}

tenTimes();
echo $number;

5. What does the following code fragment print to the browser?

$number = 50;

function tenTimes( &$n ) {
    $n = $n * 10;
}

tenTimes( $number );
echo $number;

Answers

1. The statement is false. You must always include the parentheses in your function calls, whether or not you are passing arguments to the function.

2. You must use the return keyword.

3. It prints 50. The tenTimes() function has no access to the global $number variable. When it is called, it manipulates its own local $number variable.

4. It prints 500. This example uses the global statement, which gives the tenTimes() function access to the $number variable.

5. It prints 500. By adding the ampersand to the parameter variable $n, you ensure that this argument is passed by reference. $n and $number point to the same value, so any changes to $n are reflected when you access $number.

Activities

1. Review the syntax for creating a function that accepts arguments, manipulates those values, and returns a string.

2. Create a function that accepts four string variables and returns a string that contains an HTML table element, enclosing each of the variables in its own cell.