The 5th Annual China PHP Conference


Please answer this simple SPAM challenge: max(five, zero)?
(Example: nine)

The Note You're Voting On

chriswarbo at gmail dot com
3 years ago
Note that there is a difference between a function and a function call, and both
are expressions. PHP has two kinds of function, "named functions" and "anonymous
functions". Here's an example with both:

// A named function. Its name is "double".
function double($x) {
2 * $x;

// An anonymous function. It has no name, in the same way that the string
// "hello" has no name. Since it is an expression, we can give it a temporary
// name by assigning it to the variable $triple.
$triple = function($x) {
3 * $x;

We can "call" (or "run") both kinds of function. A "function call" is an
expression with the value of whatever the function returns. For example:

// The easiest way to run a function is to put () after its name, containing its
// arguments (if any)
$my_numbers = array(double(5), $triple(5));

$my_numbers is now an array containing 10 and 15, which are the return values of
double and $triple when applied to the number 5.

Importantly, if we *don't* call a function, ie. we don't put () after its name,
then we still get expressions. For example:

= array('double', $triple);

$my_functions is now an array containing these two functions. Notice that named
functions are more awkward than anonymous functions. PHP treats them differently
because it didn't use to have anonymous functions, and the way named functions
were implemented didn't work for anonymous functions when they were eventually

This means that instead of using a named function literally, like we can with
anonymous functions, we have to use a string containing its name instead. PHP
makes sure that these strings will be treated as functions when it's
appropriate. For example:

= 'double';
$my_number = $temp(5);

$my_number will be 10, since PHP has spotted that we're treating a string as if
it were a function, so it has looked up that named function for us.

Unfortunately PHP's parser is very quirky; rather than looking for generic
patterns like "x(y)" and seeing if "x" is a function, it has lots of
special-cases like "$x(y)". This makes code like "'double'(5)" invalid, so we
have to do tricks like using temporary variables. There is another way around
this restriction though, and that is to pass our functions to the
"call_user_func" or "call_user_func_array" functions when we want to call them.
For example:

= array(call_user_func('double', 5), call_user_func($triple, 5));

$my_numbers contains 10 and 15 because "call_user_func" called our functions for
us. This is possible because the string 'double' and the anonymous function
$triple are expressions. Note that we can even use this technique to call an
anonymous function without ever giving it a name:

= call_user_func(function($x) { return 4 * $x; }, 5);

$my_number is now 20, since "call_user_func" called the anonymous function,
which quadruples its argument, with the value 5.

Passing functions around as expressions like this is very useful whenever we
need to use a 'callback'. Great examples of this are array_map and array_reduce.

<< Back to user notes page

To Top