[ Team LiB ] Previous Section Next Section

Functions Revisited

Now that we have covered arrays, we can examine some built-in functions that could help you make your own functions more flexible. If you have programmed in Perl before, you will know that you can easily create subroutines that accept a variable number of arguments. PHP provides functions that make it just as easy.

Imagine that you have created a function that accepts three string arguments and returns a single string containing each of the provided arguments wrapped in an HTML table, which includes the sum of the numbers in its final row:


function addNums( $num1, $num2 ) {
    $result = $num1 + $num2;
    $ret = "<table border=\"1\">";
    $ret .= "<tr><td>number 1: </td><td>$num1 </td></tr>";
    $ret .= "<tr><td>number 2: </td><td>$num2 </td></tr>";
    $ret .= "<tr><td>result: </td><td>$result</td></tr>";
    $ret .= "</table>";
    return $ret;
}

print addNums (49, 60);

This very simple function does its job well enough, but it is not very flexible. Imagine now that you are asked to amend the function to handle four arguments, or six, or, well, pretty much any number of integers. The simplest solution would be to ask that the calling code provide a single array containing all the numbers rather than two individual integers. This would mean that a lot of code would have to be changed in the project as a whole as well as in the function. It would be better, then, to change the function to accept any number of integers.

The tools for this job are func_num_args() and func_get_arg(). func_num_args() returns the number of arguments that have been passed to the function; it does not itself require an argument. func_get_arg() requires an integer representing the index of the argument required and returns its value. As with arrays, arguments are indexed from zero, so to get the first argument passed to a function you would use


func_get_arg (0);

It is your responsibility to check that the index you pass to func_get_arg() is within the number of arguments that were passed to the function you are testing. If the index is out of range, func_get_arg() returns false and an error is generated. Now we can rewrite our addNums() function:


function addNums() {
    $ret = "<table border=\"1\">";
    for ($x=0; $x<func_num_args (); $x++) {
        $arg = func_get_arg ($x);
        $result += $arg;
        $ret .= "<tr><td>number ". ($x+1).": </td><td>$arg</td></tr>";
    }
    $ret .= "<tr><td>result: </td><td>$result</td><tr>";
    $ret .= "</table>";
    return $ret;
}

print addNums (49, 60, 44, 22, 55);

Notice that we do not provide any argument variables at all in the function declaration. Instead, we use a for loop to access each of the arguments in turn. The loop executes just the right number of times because our upper limit is set by func_num_args().

So, given that we haven't actually used an array in this example, why is this section in a chapter on arrays? First, the way in which arguments to functions are indexed makes them somewhat array-like. Mainly, though, we have yet to cover another function: func_get_args(). func_get_args() returns an array containing all the arguments passed to our function. This means we can rewrite our example to work with a familiar foreach loop:


function addNums() {
    $args = func_get_args();
    $ret = "<table border=\"1\">";
    foreach( $args as $key => $val ) {
        $result += $val;
        $ret .= "<tr><td>number ". ($key+1).": </td><td>$val</td></tr>";
    }
    $ret .= "<tr><td>result: </td><td>$result</td></tr>";
    $ret .= </table>";
    return $ret;
}

print addNums ( 49, 60, 44, 22, 55 );

Rather than access our arguments one at a time, we simply decant the lot into an array variable called $args. Then it's simply a matter of looping through the array.

    [ Team LiB ] Previous Section Next Section