With PHP 5.5 going EOL earlier this week and the PHP 7.1 beta expected later this month, now sounds like a good time to look into a neat little feature coming in 7.1: easily converting any callable into a proper Closure using the new Closure::fromCallable() method.
If you're already familiar with closures in PHP, you can skip right ahead.
PHP has had closures since version 5.3. Think of it as similar to an anonymous function in Javascript; they're usually passed off to another method, which either calls it directly or stores it for later use.
As an example, let's look at Laravel's collection class. It has a reject method, which you can use to filter out values you don't want in the collection:
Behind the scenes, the reject method will call our closure callback for every item in the collection. If the age is less than 18, it will be rejected from our collection.
Now imagine you want to reject every value in the collection that is not a whole number. Basically, reject all floats. There's a built-in is_float function, so why don't we pass that in directly?
Unexpectedly, this will not work. Why? In addition to a closure, Laravel also allows you to pass in a single value to reject, which will remove that value from the collection. Since we've passed it a string, Laravel thinks we want to remove the 'is_float' item from the collection. Whoops!
The way around this is to actually pass in a closure and call is_float from within our closure callback:
In PHP 7.1, the Closure class has a new static fromCallable method, which automatically creates a Closure from any callbable you pass it. Using this new method, we can clean up our code a bit:
Another scenario where you'd want a closure is if you want to pass in an array-callable of a private method. As mentioned in the PHP docs, you can create a callable to a method on an object by using an array with this format: [$object, 'method']. This can be quite convenient when using a method on your class that has the logic for the callback:
$due = $orders->filter([$this, 'isDue']);
This works well, with the only caveat being that the isDue method now has to be made public - otherwise the collection class won't be able to access it.
This is where Closure::fromCallable() once again comes to the rescue. When used from within a class, the resulting closure will automatically be bound to that class, allowing it to access private methods: