In this tutorial you’ll explore anonymous functions in PHP. Anonymous functions are a PHP feature that you probably won’t use that often; however, they can be really useful in certain situations, as you’ll see.
You’ll look at the following concepts in this tutorial:
- What anonymous functions are, and how you create them
- How to assign anonymous functions to variables
- How to call anonymous functions
- Using anonymous functions to create neater callbacks, and
- Creating closures with anonymous functions.
Ready to dive into anonymous functions in PHP? Let’s go!
Anonymous functions explained
As you probably know, you define a regular function in PHP like this:
function myFunctionName() {
// (Your function code goes here)
}
When you define a function, you give it a name (myFunctionName
in the above example). PHP then lets your code refer to this function using its name. For example, you can call your function like this:
myFunctionName();
Anonymous functions are similar to regular functions, in that they contain a block of code that is run when they are called. They can also accept arguments, and return values.
The key difference — as their name implies — is that anonymous functions have no name. Here’s a code example that creates a simple anonymous function:
// Declare a basic anonymous function // (not much use on its own!) function( $name, $timeOfDay ) { return ( "Good $timeOfDay, $name!" ); };
There are two subtle but important differences between the above example and a regular function definition:
- There is no function name between the
function
keyword and the opening parenthesis ('('
). This tells PHP that you’re creating an anonymous function. - There is a semicolon after the function definition. This is because anonymous function definitions are expressions, whereas regular function definitions are code constructs.
While the above code is perfectly valid, it isn’t very useful. Since the anonymous function has no name, you can’t refer to it anywhere else in your code, so it can never be called!
However, since an anonymous function is an expression — much like a number or a string — you can do various handy things with it. For example, you can:
- Assign it to a variable, then call it later using the variable’s name. You can even store a bunch of different anonymous functions in a single array.
- Pass it to another function that can then call it later. This is known as a callback.
- Return it from within an outer function so that it can access the outer function’s variables. This is known as a closure.
You’ll explore these three techniques in the rest of this tutorial.
Assigning anonymous functions to variables
When you define an anonymous function, you can then store it in a variable, just like any other value. Here’s an example:
// Assign an anonymous function to a variable $makeGreeting = function( $name, $timeOfDay ) { return ( "Good $timeOfDay, $name!" ); };
Once you’ve done that, you can call the function using the variable’s name, just like you call a regular function:
// Call the anonymous function echo $makeGreeting( "Fred", "morning" ) . "<br>"; echo $makeGreeting( "Mary", "afternoon" ) . "<br>";
This produces the output:
Good morning, Fred! Good afternoon, Mary!
You can even store several functions inside an array, like this:
// Store 3 anonymous functions in an array $luckyDip = array( function() { echo "You got a bag of toffees!"; }, function() { echo "You got a toy car!"; }, function() { echo "You got some balloons!"; } );
Once you’ve done that, your code can decide which function to call at runtime. For example, it could call a function at random:
// Call a random function $choice = rand( 0, 2 ); $luckyDip[$choice]();
Using anonymous functions as callbacks
One common use of anonymous functions is to create simple inline callback functions. A callback function is a function that you create yourself, then pass to another function as an argument. Once it has access to your callback function, the receiving function can then call it whenever it needs to. This gives you an easy way to customise the behaviour of the receiving function.
Many built-in PHP functions accept callbacks, and you can also write your own callback-accepting functions. Let’s look at a couple of built-in functions that use callbacks, and see how to use them.
Using array_map(
) to run a callback function on each element in an array
PHP’s array_map()
function accepts a callback function and an array as arguments. It then walks through the elements in the array. For each element, it calls your callback function with the element’s value, and your callback function needs to return the new value to use for the element. array_map()
then replaces the element’s value with your callback’s return value. Once it’s done, array_map()
returns the modified array.
array_map()
works on a copy of the array you pass to it. The original array is untouched.
Here’s how you might use array_map()
with a regular callback function:
// Create a regular callback function... function nameToGreeting( $name ) { return "Hello " . ucfirst( $name ) . "!"; } // ...then map the callback function to elements in an array. $names = array( "fred", "mary", "sally" ); print_r( array_map( nameToGreeting, $names ) );
This code creates a regular function, nameToGreeting()
, that takes a string, $name
, uppercases the first letter, prepends "Hello "
, and returns the result. Then, on line 8, the code passes this callback function to array_map()
, along with an array of names to work with, and displays the result:
Array ( [0] => Hello Fred! [1] => Hello Mary! [2] => Hello Sally! )
While this code works, it’s a bit cumbersome to create a separate regular function just to act as a simple callback like this. Instead, we can create our callback as an inline anonymous function at the time we call array_map()
, as follows:
// A neater way: // Map an anonymous callback function to elements in an array. print_r ( array_map( function( $name ) { return "Hello " . ucfirst( $name ) . "!"; }, $names ) );
This approach saves a line of code, but more importantly, it avoids cluttering up the PHP file with a separate regular function that is only being used as a one-off callback.
Custom array sorting with usort()
Another common use of callbacks is with PHP’s usort()
function. This function lets you sort arrays using a sorting callback function that you write yourself. This is particularly handy if you need to sort an array of objects or associative arrays, since only you, as the coder, know the best way to sort such complex structures.
Let’s create an array of associative arrays, where each associative array has a name
key and an age
key:
$people = array( array( "name" => "Fred", "age" => 39 ), array( "name" => "Sally", "age" => 23 ), array( "name" => "Mary", "age" => 46 ) );
Now, say we want to sort the array in ascending order of age. We can’t use the regular PHP array sorting functions, since these don’t know anything about the age
key. Instead, we can call usort()
and pass in an anonymous callback function that sorts the array by age, like this:
usort( $people, function( $personA, $personB ) { return ( $personA["age"] < $personB["age"] ) ? -1 : 1; } ); print_r( $people );
This produces the result we want:
Array ( [0] => Array ( [name] => Sally [age] => 23 ) [1] => Array ( [name] => Fred [age] => 39 ) [2] => Array ( [name] => Mary [age] => 46 ) )
Creating closures with anonymous functions
Another common use of anonymous functions is to create closures. A closure is a function that retains access to the variables in its enclosing scope, even if that scope has since disappeared.
For example:
- A function,
myFunction()
, contains a local variable (or parameter) called$myVar
. - The function also defines and returns an anonymous function that accesses
$myVar
. - Some other code calls
myFunction()
and gets back the anonymous function, which it stores in$anonFunction
. By this time,myFunction()
has, of course, finished running. - If the code now calls
$anonFunction()
, the anonymous function can still access the$myVar
local variable that was inmyFunction()
, even thoughmyFunction()
is no longer running! The anonymous function, together with its reference to the$myVar
variable, constitute a closure.
Rather confusingly, the PHP manual refers to anonymous functions as closures. They are not the same thing! Anonymous functions are used to create closures.
Closures can be difficult to get your head around at first, but once you grasp the concept, they let you write clean, powerful and flexible code. Let’s look at a couple of examples of closures to make things clearer.
A simple closure
We’ll start by creating a very simple closure using an anonymous function:
// A simple example of a closure function getGreetingFunction() { $timeOfDay = "morning"; return ( function( $name ) use ( &$timeOfDay ) { $timeOfDay = ucfirst( $timeOfDay ); return ( "Good $timeOfDay, $name!" ); } ); }; $greetingFunction = getGreetingFunction(); echo $greetingFunction( "Fred" ); // Displays "Good Morning, Fred!"
Let’s walk through this code:
getGreetingFunction()
getGreetingFunction()
initialises a local variable,$timeOfDay
, on line 5, and on lines 7-10 it also defines and returns an anonymous function (described below).- The anonymous function
On line 8, the anonymous function manipulatesgetGreetingFunction()
‘s local$timeOfDay
variable by converting its first letter to uppercase, and on line 9 it returns a greeting string that contains$timeOfDay
‘s value.-
- The
use
keyword
Normally, the anonymous function wouldn’t have access to the$timeOfDay
variable, since that variable is local togetGreetingFunction()
‘s scope only. However, theuse
keyword on line 7 tells PHP to let the anonymous function access$timeOfDay
. This lets us create the closure. - The ampersand
The ampersand (&
) before$timeOfDay
tells PHP to pass a reference to the$timeOfDay
variable into the anonymous function, rather than just copying the variable’s value. This allows the anonymous function to manipulate$timeOfDay
directly. Strictly speaking, a closure’s function should always access variables in its enclosing scope by reference. That said, if you know that you won’t need to change the value of a variable then you can omit the ampersand to pass the variable by value instead.
- The
-
- Calling
getGreetingFunction()
On line 13, we callgetGreetingFunction()
and get back the returned anonymous function, which we store in a$greetingFunction
variable.Note that, by this point,
getGreetingFunction()
has finished running. In normal circumstances, its local variable,$timeOfDay
, would have fallen out of scope and disappeared. However, because we’ve created a closure using the anonymous function (now stored in$greetingFunction
), the anonymous function can still access this$timeOfDay
variable. - Calling the anonymous function
On line 14, we call our anonymous function. It manipulates the value of the$timeofDay
variable inside the closure by converting its first letter to uppercase, then it returns a greeting containing$timeOfDay
‘s new value, which is"Morning"
.
That, in a nutshell, is how you create a closure in PHP. It’s a trivial example, but the important point to note is that the returned anonymous function can still access its enclosing function’s $timeOfDay
local variable, even after the enclosing function has finished running.
Using closures to pass additional data to callbacks
Now that we’ve seen how to create a closure, let’s look at a common practical use for them.
When you pass a callback function to the PHP usort()
function, and usort()
calls your callback, the callback receives the two arguments passed to it by usort()
— that is, the two values in the array to compare.
But what if you wanted your callback function to receive extra information? For example, taking our usort()
example from earlier in the article, we might want to pass an additional $sortKey
argument to our callback to tell it which key it should use for sorting the array ("name"
or "age"
).
However, usort()
— not us — calls our callback. Since it’s called within usort()
‘s scope, we don’t have a chance to pass additional arguments to the callback at the time it’s called.
Closures to the rescue! By returning our callback function from inside another function and creating a closure, we can get the outer function to accept $sortKey
as a parameter, then pass $sortKey
to the callback inside the closure. Here’s the complete code:
$people = array( array( "name" => "Fred", "age" => 39 ), array( "name" => "Sally", "age" => 23 ), array( "name" => "Mary", "age" => 46 ) ); function getSortFunction( $sortKey ) { return function( $personA, $personB ) use ( $sortKey ) { return ( $personA[$sortKey] < $personB[$sortKey] ) ? -1 : 1; }; } echo "Sorted by name:<br><br>"; usort( $people, getSortFunction( "name" ) ); print_r( $people ); echo "<br>"; echo "Sorted by age:<br><br>"; usort( $people, getSortFunction( "age" ) ); print_r( $people ); echo "<br>";
This code displays the expected output:
Sorted by name: Array ( [0] => Array ( [name] => Fred [age] => 39 ) [1] => Array ( [name] => Mary [age] => 46 ) [2] => Array ( [name] => Sally [age] => 23 ) ) Sorted by age: Array ( [0] => Array ( [name] => Sally [age] => 23 ) [1] => Array ( [name] => Fred [age] => 39 ) [2] => Array ( [name] => Mary [age] => 46 ) )
Let’s walk through this code to see how it works:
-
- Create an array of people.
First we create our usual array of people. Each person is represented by an associative array with two keys:"name"
and"age"
. - Define
getSortFunction()
.
Next we define a regular function,getSortFunction()
, that accepts a$sortKey
parameter. This is the key that we want our sorting callback function to use. WithingetSortFunction()
, we… - Create the closure.
On lines 8-10,getSortFunction()
defines and returns an anonymous function, which is the sorting function that we’ll pass tousort()
. The anonymous function accepts the usual two array elements to sort —$personA
and$personB
— but it also uses theuse
keyword to access the$sortKey
parameter, which is within the scope of the enclosinggetSortFunction()
function. This creates the closure. It then uses$sortKey
to determine which key to use for the comparison (either"name"
or"age"
).Remember: Since we’ve created a closure, the anonymous function still has access to the value of the
$sortKey
parameter aftergetSortFunction()
has finished running. - Sort the array.
Finally our code sorts the array, first by name and then by age. To do this, it callsgetSortFunction()
, passing in the key to sort by ("name"
or"age"
).getSortFunction()
then returns an appropriate anonymous sort function that uses the supplied sort key. The code then passes this anonymous function tousort()
, along with the array to sort.
- Create an array of people.
You can use this trick any time you need to pass additional data to a callback function.
Closures are quite a broad and subtle topic. If you’re not familiar with them, check out the following good articles on anonymous functions and closures in PHP and closures and lambda functions, which explain in detail exactly what a closure is (and isn’t).
Summary
In this tutorial you looked at anonymous functions in PHP, and saw how to use them in various situations. You learned:
-
-
- That an anonymous function is much like a regular function, except it has no name, and is an expression rather than a code construct.
- How to assign an anonymous function to a variable, and how to call the anonymous function using the variable.
- Ways to use inline anonymous functions as callbacks to create neater, tidier code.
- How to create closures using anonymous functions. Closures are useful for many things, including making code more readable, avoiding global variables, and creating customisable callback functions.
-
I hope you found this tutorial helpful, and that you now feel confident creating and using anonymous functions in your PHP code. Have fun!
[Image credits:
Men,
megaphone,
gift boxes
via Shutterstock]
daveporter says
Thanks for article…
Some of it is a bit over my head, but I get the general gist!
One thing that has me confused is the usort example.
Should this line:
return ( $personA[“age”] < $personB[“age”] ) ? -1 : 1;
Have “name” for $personA ?
Cheers, Dave
chrishirst says
name??
That line is the equvalent of
jarimos says
Hello. Thanks for all your nices tutorials. I am learning a lot.
I Get a warning in this line
print_r( array_map( nameToGreeting, $names ) );
And it dissapear if I write this
print_r( array_map( ‘nameToGreeting’, $names ) );
the difference are the quotes ‘nameToGreeting’
Thanks a lot again 🙂
daveporter says
Hi Jarimos,
By putting the function name in quotes you are just masking the fact that it must be missing ?
It looks like this in the article…
// Create a regular callback function…
function nameToGreeting( $name ) {
return “Hello ” . ucfirst( $name ) . “!”;
}
Check your syntax and ensure it is accurate!
HTH, Dave
Ray says
Hi there,
You say “Note that, by this point, getGreetingFunction() has finished running. In normal circumstances, its local variable, $timeOfDay, would have fallen out of scope and disappeared. However, because we’ve created a closure using the anonymous function (now stored in $greetingFunction), the anonymous function can still access this $timeOfDay variable.“.
I cant shake off the idea that $greetingFunction is a reference to getGreetingFunction(). You say getGreetingFunction has finished running but isnt it so that the named function is called every time the variable $greetingFunction is used? I cant get my head around the fact that the named function as well as the anonymous function runs whenever the variable is used (since it references the named function).
Andrey White says
I also thought the same way, and was very confused, until recognized the fact, that, when you assign getGreetingFunction() to a variable, in this case, you assign NOT this function itself, but RESULT of this function, and result is ANOTHER – anonymous function, that can take value of variable from “parent” function.
For example:
a$ = sqrt(9); sqrt() is function and returns 3 as result, and we assign it to $a variable
$greetingFunction = getGreetingFunction(); getGreetingFunction() is function, but returns not itself, but another function, that is inside it – “RETURN ( function( $name ) ……” . So, every time we use $greetingFunction, we use only this “part of code” :
function( $name ) use ( &$timeOfDay ) {
$timeOfDay = ucfirst( $timeOfDay );
return ( “Good $timeOfDay, $name!” );
}
Variable $timeOfDay at this moment already exists and assigned. We took it from “parent” function getGreetingFunction(), that has finished running.
Vikarm says
Hi,
Can I call anonymous function inside another anonymous function?
For example:
chrishirst says
Provided the functions are not reiterative (calling an instance of themselves), there should be no problem.