As the title suggests, I’ve made a discovery. I’m a little ashamed it took me this long to make this discovery, but it is a glorious discovery nonetheless. PHP SUPPORTS CLOSURES (anonymous functions). That’s right! You can use closures in PHP!
Now that’s out of the way you may be saying “Well, yeah… that’s so PHP 5.3.” That’s valid, but if you already know that, then you can skip this all together. I’m writing this to the person who is asking “Calm down, Captain Crazypants, what’s a closure?”, or to the person who lives and dies by JavaScript and jQuery and wants to use some of their scriptfoo in PHP.
So What Is a Closure Anyway?
Closures (also known as anonymous functions or lambda functions) are just that — Anonymous or closed. They don’t follow the standard function declaration, and can be created inline. If you’ve used ANY modern JavaScript library, you’ve already done this.
public function foo(){
//do stuff
}
vs
function(){
//do stuff
}
Most notably, closures let you create entire functions as arguments to other functions. This feature is typically utilized by passing a callback to some utility function (which is basically the working model behind jQuery). In the example above, you’ll see the standard function declaration for function foo — pretty standard stuff. At this point, you can call foo() and have it do work.
The second block of code, just simply calls function(). Now, this is not a named function (hence anonymous), but this syntax can be used inside of other function calls.
public function foo($callback){
//do work;
//do more work;
//all done, time to call the callback
if(is_callable($callback)){
$callback();
}
}
//body of program
//doing stuff
foo(function(){
//do custom callback stuff
});
In this example, you can see that we start with the standard function declaration that takes a $callback variable. At the end of foo, we call the callback as if it were a function $callback();. In the program code below that, you can see that instead of using the name of a predefined function, we are using the anonymous function syntax to create a function on the fly to pass to foo. It also might make sense to note there that by setting foo up to take a callback, we can change the behavior of foo on each call by changing the callback passed to it. This makes for some pretty powerful utility. Also of note, see that we are using is_callable to verify that $callback is a function before trying to call it (safety first!).
Real World Example
I had actually stumbled across this while working with the usort function. Usort is an array sorting function where you can supply a function that does the comparison of the array elements — really handy for sorting arrays of objects.
In my scenario, I had an object that among other things had a name field on which I wanted to sort. The regular sorting functions wouldn’t cut it, so I started researching usort. After seeing the signature of the function, I started writing yet another function to pass to usort to do the sorting, but thankfully looked at ONE more example… one that used a closure. Aside from eliminating my need to create an extra function, I got super excited that PHP supported closures.
So, let’s get to it.
To sort my array of objects by object name, the call would look like this:
usort($array, function($item1, $item2){
return strcmp($item1->name, $item2->name);
});
When usort goes to sort the array, it calls the callback (the closure you provide) to compare the two keys. The values are then put in order based on the return value of the function.
I hope that these simple examples adequately illustrated the power of closures and the utility it can bring to your code. Play around with it — I promise you won’t be sorry.