Closures coming in PHP 5.3 and that’s a Good Thing
February 20, 2009 – 5:48 pm Tags: PHPPHP 5.3 will be introducing closures to PHP. Closures, also known as anonymous functions, will allow you to declare functions “inline” and store them in variables. While the syntax may seem a bit weird compared to how it is in languages like JavaScript, closures will be a useful addition to the language. However, like reflection, it’s a feature that may not immediately show it’s usefulness…
Simple example
Let’s take a quick example of how you would define a closure:
$closure = function($param) { echo $param; }; //This one takes value of someVar and "stores" it in the closure's scope even if //we later change the value of someVar outside it. We assume that $somerVar is defined before this $closure2 = function($param) use ($someVar) { echo $param . ' ' . $someVar; };
Note that in earlier PHP versions, you can achieve a similar effect by using create_function. There are some problems with create_function, though, and using it is generally not recommended. Closures in 5.3 will work without the issues of create_function – not to mention have a much better syntax as you won’t have to escape your stuff in a string!
Next, let’s take a look at some ways you can immediately benefit from closures.
Use case: outputting HTML
In bigger applications it’s often typical to have more than one or two similar views of data. For example, you may want to have a paginated list of some kind of data stored in the database.
To preserve similar styling across your application, you should put code which outputs common elements such as these lists inside functions or classes so they are easy to reuse. However, there’s one problem here: what if you have some data, which requires a bit different formatting for the rows in the list? Maybe it needs an icon, or maybe you want to add some JavaScript code to run when you hover over the item.
You could add some code to the function, which allows the user to pass some parameters to it which change the way the rows are outputted, but this can lead to much clutter in the function itself, and when you need yet another slightly different list, you again need to modify the function.
Or, you could use a closure to provide a so-called “formatter” function to it!
function item_list(array $items, $formatter = null) { //create the default formatter if($formatter == null) { $formatter = function($row) { return '<p>' . $row . '</p>'; }; } $html = '<h2>Listing:</h2>'; foreach($items as $item) { $html .= $formatter($item); } return $html; }
So there we have an example list-creator function. It can take two arguments: the array of data to output, and an optional formatter.
//show a list of numbers using the default format: echo item_list(array(1,2,3)); //let's show it in bold instead: echo item_list(array(1,2,3), function($row) { return '<p><strong>' . $row . '</strong></p>'; });
Other uses
Closures could also be used as event handlers. If you’ve used JavaScript, chances are you’ve used something like window.onload = function() { … }.
Another good use is with functions such as array_map or usort: They take a function as an argument, which is then called once for each item in the array passed as the other argument. These functions aren’t always very complex, or maybe they aren’t used in more than one place, so you wouldn’t necessarily need to have them as separate functions.
For example, a recent question in #zftalk was about calling a specific method in each object in an array, and putting the result to another array:
$results = array(); array_map(function($row) use (&$results) { $results[] = $row->someMethod(); }, $someArray);
In this example, the use() is needed for the closure to be able to access $results. We also need to pass results as a reference, since the modifications we do inside the closure won’t otherwise affect it. What this code does could be achieved with a loop too.
Maybe a more typical example of a one-use function is with usort, which sorts an array by using a user defined sorting function:
$arr = array(2,1,3); usort($arr, function($a, $b) { return $a < $b ? 1 : -1; });
Difference between use() and globals
You may wonder why do you need use() when you could use globals. It’s true that in a simple case using global $foo or use($foo) are pretty much the same, but there is a difference.
Imagine a case where you write a function, and there’s a local variable inside the function. You want to use this variable inside the closure.
In this case, we need to use the use clause. If we used global, it would attempt to look up the variable from the global scope. Even if there is no such variable available globally, it won’t use the local variable in the function. With use(), the local variable can be used inside the closure.
In closing
As you can see from the example, closures are quite useful if you just know how to use them. We even could modify the listing function to output some details from a class – we can pass it an array of class instances, and a function which calls a specific method of the class instead of just showing the $row variable itself. Too bad it’s probably going to take a while before PHP 5.3 is common enough to rely on this feature much.

27 Responses to “Closures coming in PHP 5.3 and that’s a Good Thing”
“Closures, also known as anonymous functions”
wrong.
Closures and anonymous functions are not the same thing/concept.
By cirpo on Feb 20, 2009
Thanks for making it clear. They are similar, but not exactly the same even though people do use both names for them.
By Jani Hartikainen on Feb 20, 2009
Is this purely usefull for functional style programming?
The example provided seems to be served by the decorator oop pattern.
DM
By DangerMouse on Feb 21, 2009
Hey Jani
Nice article. Just to clarify is the “uses” clause not required in the array_map example?
Since the closure accesses the $results var in the global scope?
By phpslacker on Feb 21, 2009
I was wondering if closure was acceptable as argument in array_map() and other from that kind ?
By Radoslav Stankov on Feb 21, 2009
phpslacker, I’m relatively sure it’s like that.
Radoslav, I’ve been attempting to install 5.3′s beta version, but with no luck. The Windows one doesn’t seem to have the new features in it… Anyways, I would assume yes, as normally it would accept a callback, ie. function name or array for class methods.
It wouldn’t be a very useful feature if it didn’t work like that
By Jani Hartikainen on Feb 21, 2009
This example won’t work for several reasons, and you don’t seem to understand how array_map works.
$results = array();
array_map(function($row) { $results[] = $row->someMethod(); }, $someArray);
Your “item_list”-example has been possible to implement (nicely) in PHP since 4.0 when it got OOP through the decorator pattern or even earlier with a dynamic dispatch table (bit contrived though)
You also seem to fail to understand how usort (or sorting in general?) works:
usort($arr, function($a, $b) { return $a < $b; });
will not produce correct results, since you need to return a number in the sequence [-1, 0, 1] for it to work properly.
You also seem to mix up closures and anonymous function which ar not the same thing.
Not to mention your “item_formater” example is horrible, mixing html and php like that.
And, this code will not work either:
$closure2 = function($param) uses ($someVar) { echo $param . ‘ ‘ . $someVar; };
demonstrated by this example: $c = function() use($foo) { echo $foo; }; $c(); which will give you a E_NOTICE about an undefined variable.
And last, as you say in closing that “losures are quite useful if you just know how to use them” is true – however you seem to lack any understanding of the concept and provide only examples that 1) don’t work properly, 2) generate runtime errors or 3) would be better implemented some way else.
By Fredrik Holmström on Feb 23, 2009
Hey!! Knock it off! Brow beating the guy for posting a slightly misguided intro to PHP’s closures/anonymous functions isn’t going to solve anything.
It’s still PHP, after all!
::ducks!::
By Anonymous Coward on Feb 23, 2009
Fredrik, thanks for pointing out the stupid mistake in usort. I feel like a newbie because I wrote that sorting function totally wrong… that’s what you get for quickly writing a post and then declaring “YES! This post is now DONE!”
I will correct the usort example in a bit. However, what comes for the rest of your critique, maybe you should post the “correct” way to do the list formatter thing with decorators or whatever you feel is better?
I don’t exactly see why the way I did it is particularily bad – you do need to mix html + php at times, and I think it’s okay as long as it’s not something like sticking an SQL query there.
Oh, and perhaps you should check your comment for mistakes too. I’m not going to start pointing them out, I’m sure you can see them yourself
By Jani Hartikainen on Feb 23, 2009
Oh, and to Radoslav or anyone else who’s been wondering if the usort and array_map functions actually work with closures…
The answer is yes, yes they do. I managed to get 5.3 running now, and it indeed does work like that. I updated one of the examples to reflect the way the use() clause works instead of what I had guessed earlier.
By Jani Hartikainen on Feb 23, 2009
Thank you, short and sweet read!
By MJ on Feb 23, 2009
This would be great in conjunction with PHPLinq, http://www.phplinq.net.
By Maarten Balliauw on Feb 23, 2009
Jani: You still fail to grasp array_map after my points, this code:
$results = array();
array_map(function($row) use (&$results) { $results[] = $row->someMethod(); }, $someArray);
should be written as such:
$results = array_map(function($row) { return $row->someMethod(); }, $someArray);
Also, this (will sort edgecases weirdly):
$arr = array(2,1,3);
usort($arr, function($a, $b) { return $a < $b ? 1 : -1; });
should be
$arr = array(2,1,3)
usort($arr, function($a, $b) { return $a $b) -1 : 0 ; });
Also, this phrase: “It’s true that in a simple case using global $foo or use($foo) are pretty much the same, but there is a difference”. They are not even close to the same even in simple cases, and even while you can “use globals instead of use()” sometimes they shouldn’t be explained as “almost the same”.
By Fredrik Holmström on Feb 23, 2009
Ehm… wordpress slaughtered my code fr some reason… the usort should be (just the return statement)
$a > $b ? 1 : ($a < $b ? -1 : 0);
And I noticed that you’re original function will sort backwards in addition to not handle equality.
By Fredrik Holmström on Feb 23, 2009
Sigh, wordpress really is getting on my nerves, anyway… yeah there probably are a lot of spelling mistakes in my (three?) comments, but I’ve always had a “hard time” spelling, even in my native language (swedish), never had any problems with code though ;P
By Fredrik Holmström on Feb 23, 2009
The point with array_map was to demonstrate accessing the external variable, but I suppose it could’ve been done by using something else, since by returning the value you get pretty much the same effect w/ array_map.
The usort function will handle equality just fine without the extra case, as it doesn’t matter if we sort equal numbers after or before their own equals.
By Jani Hartikainen on Feb 23, 2009
I think closures work better for the list example here than a decorator would. Using a decorator class would require much more code than a closure and the closure can be declared inline as he shows so if it’s a one time modification as that kind of things usually are it would be simpler too. KISS!
By Big Mac on Feb 24, 2009
No need for closure here, while they are great, it seems like syntax sugar for more compact non-reusable code, unless someone wants to create a jQuery like MVC framework for PHP:
/**
* This wraps entries around with tags
*/
function p_formatter($row)
{
return “”.$row.”\n”;
}
/**
* This wraps entries around with tags
*/
function pstrong_formatter($row)
{
return ““.$row.”\n”;
}
function item_list(array $items, $formatter = null) {
//create the default formatter
if($formatter == null) {
$formatter = “p_formatter”;
}
$html = “Listing:\n”;
foreach($items as $item) {
$html .= call_user_func_array($formatter, $item);
}
return $html;
}
echo item_list(array(1,2,3));
echo “\n”;
echo item_list(array(1,2,3), “pstrong_formatter”);
By Fred on Feb 24, 2009
$closure = function($param) { echo $param; }; is not a closure. It is a function named ‘closure’ that takes the argument ‘param’ and echoes it.
A closure is a function that is evaluated in an environment containing one or more bound variables.
For an understanding of closures read the Wikipedia entry on it:
http://en.wikipedia.org/wiki/Closure_(computer_science)
By takos on Mar 2, 2009
The difference between an anonymous function and a closure is that a closure is a function that closes over one or more free variables, an anonymous function is a function created anonymously in a given language.
Anonymous function:
$v = 1;
$f = function($x) { return $x+1; }
Closure:
$v = 1;
$f = function($x) use ($v) { return $x+$v; }
It’s probably best just to call them all ‘functions’, until you want to be specific, and then you say ‘anonymous function’ or ‘closure’.
By Anonymous on Apr 29, 2009
Nice read, however Im still confused where is the difference between use() and global??
LOL, the usort() function could be:
usort($arr, function($a, $b) { return $a – $b; });
b/c there is no limitation to 1 or -1 only…
By Orkan on May 16, 2009
I think conflating anonymous functions and closures, even though they are technically different, comes from the fact that anonymous functions are first class values and that implementing first class functions without closures is not done anymore (see http://en.wikipedia.org/wiki/Funarg_problem)
By zorg on Aug 9, 2009
This is the first article when I googled about “PHP closure”. It clarify my concern on how PHP actually have closure. Without “use”, PHP doesn’t actually have closure, but just anonymous function.
By Morgan Cheng on Sep 20, 2009
cirpo, you’re wrong. He didn’t say they are the same, he said: “Closures, also KNOWN as anonymous functions”
His statement is correct, they are both known by both names, however – you are correct in saying that they are technically different.
Subtle but important difference.
By Kirk Bushell on Jan 7, 2010