only for RuBoard - do not distribute or recompile Previous Section Next Section

2.10 User-Defined Functions

Functions provide a way to group together related statements into a cohesive block. For reusable code, a function saves duplicating statements and makes maintenance of the code easier.

We've already presented many examples of function calls in this chapter. Once written, a user-defined function is called in exactly the same way. Consider an example of a simple user-developed function as shown in Example 2-6.

Example 2-6. A user-defined function to output bold text
<!DOCTYPE HTML PUBLIC 
  "-//W3C//DTD HTML 4.0 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Simple Function Call</title>
</head>
<body bgcolor="#ffffff">
<?php

function bold($string)
{
  echo "<b>" . $string . "</b>\n";
}

// First example function call (with a static string)
echo "this is not bold\n";
bold("this is bold");
echo "this is again not bold\n";

// Second example function call (with a variable)
$myString = "this is bold";
bold($myString);
?>
</body></html>

The script defines the function bold( ), which takes one parameter, $string, and prints that string prefixed by a bold <b> tag and suffixed with a </b> tag. The bold( ) function, defined here, can be used with a string literal expression or a variable, as shown.

Functions can also return values. For example, consider the following code fragment that declares and uses a function heading( ), which returns a string using the return statement:

function heading($text, $headingLevel)
{
  switch ($headingLevel)
  case 1:
    $result = "<h1>" . ucwords($text) . "</h1>";
    break;

  case 2:
    $result = "<h2>" . ucwords($text) . "</h2>";
    break;

  case 3:
    $result = "<h3>" . ucfirst($text) . "</h3>";
    break;

  default:
    $result = "<p><b>" . ucfirst($text) . "</b>";

  return($result);
}

$test = "user defined functions";
echo heading($test, 2);

The function takes two parameters: the text of a heading and a heading level. Based on the value of $headingLevel, the function builds the HTML suitable to display the heading—changing the case of the $text appropriately. The previous fragment generates the string:

<h2>User Defined Functions</h2>

The variable that is returned by a return statement can optionally be placed in parentheses: the statements return($result) and return $result are identical.

2.10.1 Argument Types and Return Types

The argument and return types of a function aren't declared when the function is defined. PHP allows arguments of any type to be passed to the function, and as with variables, the return type is determined when a result is actually returned. Consider a simple function that divides two numbers:

function divide($a, $b)
{
    return ($a/$b);
}

$c = divide(4, 2);  // assigns an integer value = 2
$c = divide(3, 2);  // assigns a float value = 1.5
$c = divide(4.0, 2.0); // assigns a float value = 2.0

If the types of arguments passed to the function are critical, they should be tested as shown earlier in Section 2.1.3.

2.10.2 Variable Scope

Variables used inside a function are different from those used outside a function. The variables used inside the function are limited to the scope of the function (there are exceptions to this rule, which are discussed later in this section). Consider an example that illustrates variable scope:

function doublevalue($var)
{
  $temp = $var * 2;
}

$variable = 5;
doublevalue($variable);
echo "\$temp is: $temp";

This example outputs the string:

$temp is:

and no value for $temp. The scope of the variable $temp is local to the function doublevalue( ) and is discarded when the function returns.

The PHP script engine doesn't complain about undeclared variable being used. It just assumes the variable is empty. However, this use of an undefined variable can be detected using the error-reporting settings discussed later, in Section 2.12.

If you want to use a value that is local to a function elsewhere in a script, the easiest way to do so is to return the value of the variable. This example achieves this:

function doublevalue($var)
{
  $returnVar = $var * 2;
  return($returnVar);
}

$variable = 5;
$temp = doublevalue($variable);
echo "\$temp is: $temp";

The example prints:

$temp is: 10

You could have still used the variable name $temp inside the function doublevalue( ). However, the $temp inside the function is a different variable from the $temp outside the function. The general rule is that variables used exclusively within functions are local to the function, regardless of whether an identically named variable is used elsewhere. There are two exceptions to this general rule: variables passed by reference and those declared global in the function aren't local to the function.

2.10.2.1 Global variables

If you want to use the same variable everywhere in your code, including within functions, you can do so with the global statement. The global statement declares a variable within a function as being the same as the variable that is used outside of the function. Consider this example:

function doublevalue(  )
{
  global $temp;
  $temp = $temp * 2;
}

$temp = 5;
doublevalue(  );
echo "\$temp is: $temp";

Because $temp is declared inside the function as global, the variable $temp used in doublevalue( ) is a global variable that can be accessed outside the function. Because the variable $temp can be seen outside the function, the script prints:

$temp is: 10

A word of caution: avoid overuse of global as it makes for confusing code.

The global variable declaration can be a trap.

In some other languages, global variables are usually declared global outside the functions and then used in the functions.

In PHP, it's the opposite: to use a global variable inside a function, declare the variable as global inside the function.

An alternative to using global is to return more than one variable from a function by creating and returning an array of values. A better approach is to pass parameters by reference instead of by value. We discuss the latter approach in the next section.

2.10.3 How Variables Are Passed to Functions

By default, variables are passed to functions by value, not by reference. The following example:

function doublevalue($var)
{
  $var = $var * 2;
}      

$variable = 5;
doublevalue($variable);
echo "\$variable is: $variable";

has the output:

$variable is: 5

The parameter $variable that is passed to the function doublevalue( ) isn't changed by the function. What actually happens is that the value 5 is passed to the function, doubled to be 10, and the result lost forever! The value is passed to the function, not the variable itself.

2.10.3.1 Passing arguments by reference

An alternative to returning a result or using a global variable is to pass a reference to a variable as an argument to the function. This means that any changes to the variable within the function affect the original variable. Consider this example:

function doublevalue(&$var)
{
  $var = $var * 2;
}      

  $variable = 5;
  doublevalue($variable);
  echo "\$variable is: $variable";
?>

This prints:

$variable is: 10

The only difference between this example and the last one is that the parameter $var to the function doublevalue( ) is prefixed with an ampersand character: &$var. The ampersand means that a reference to the original variable is passed as the parameter, not just the value of the variable. The result is that changes to $var in the function affect the original variable $variable outside the function.

Functions that are defined with arguments that are references to variables can't be called with literal expressions, because the function expects a variable to modify. PHP reports an error when such a call is made.

2.10.3.2 Assigning by reference

Referencing with the ampersand can also be used when assigning variables, which allows the memory holding a value to be accessed from more than one variable. This example illustrates the idea:

$x = 10;
$y = &$x;
$y++;
echo $x;
echo $y;

Here's how it prints:

11
11

Because $y is a reference to $x, any change to $y affects $x. In effect, they are the same variable. So, by adding 1 to $y, you also add 1 to $x, and both are equal to 11.

The reference $y can be removed with:

unset($y);

This has no effect on $x or its value.

2.10.3.3 Default argument values

PHP allows functions to be defined with default values for arguments. A default value is simply supplied in the argument list using the = sign. Consider the modified heading( ) function described earlier:

function heading($text, $headingLevel = 2)
{
  switch ($level)
  case 1:
    $result = "<h1>" . ucwords($text) . "</h1>";
    break;

  case 2:
    $result = "<h2>" . ucwords($text) . "</h2>";
    break;

  case 3:
    $result = "<h3>" . ucfirst($text) . "</h3>";
    break;

  default:
    $result = "<p><b>" . ucfirst($text) . "</b>";

  return($result);
}

$test = "user defined functions";
echo heading($test);

When calls are made to the heading( ) function, the second argument can be omitted, and the default value 2 is assigned to the $headingLevel variable.

2.10.4 Reusing Functions with Include and Require Files

To use functions across many PHP scripts, PHP supports the include statement and the require directive.

If you decide you wish to reuse the bold( ) function from Example 2-6 in more than one script, you can store it in an include file. For example, you can create a file called functions.inc and put the bold( ) function in the file:

<?php
function bold($string)
{
  echo "<b>" . $string . "</b>\n";
}
?>

Any PHP code in an include file must be surrounded by the PHP start and end script tags. The PHP script engine treats the contents of include files as HTML unless script tags are used.

In a script, you can then use the include statement to provide access to the function bold( ):

<html>
<head>
  <title>Simple Function Call</title>
</head>
<body bgcolor="#ffffff">
<?
include "functions.inc";

// First example function call (with a static string)
echo "this is not bold\n";
bold("this is bold");
echo "this is again not bold\n";

// Second example function call (with a variable)
$myString = "this is bold";
bold($myString);
?>
</body></html>

The script works as before, but the function bold( ) can now be reused across several scripts by including functions.inc. We use include files throughout Chapter 4 through Chapter 13.

Be careful when using the include statement. Including the same file twice or declaring a function in the script that is already in an include file causes PHP to complain about the function being redefined.

The include statement is treated in the same way as other statements. For example, you can conditionally include different files using the following code fragment:

if ($netscape == true)
{
  include "netscape.inc";
}
else
{
  include "other.inc";
}

The file is included only if the include statement is executed in the script. The braces used in this example are necessary: if they are omitted, the example doesn't behave as expected.

If a file must always be included, the require directive should be used instead of include. The require directive is processed before the script is executed, and the contents of the required file are always inserted in the script. This is useful for creating reusable HTML. For example, if you want to add the same header or footer to every page on a site—regardless of errors or other problems—require makes this easy and simple to maintain.

Consider the following HTML fragment:

<hr><br>(c) 2001 Hugh E. Williams and David Lane

If you want this fragment at the base of every page, the fragment can be stored in a file footer.inc and the directive added to the bottom of every script you develop:

require "footer.inc";

The benefit is that if you want to update the HTML footer, you need to do so in only one file.

only for RuBoard - do not distribute or recompile Previous Section Next Section