Closures in PHP... what, precisely, are they and when would you need to use them?

Solution 1:

PHP will support closures natively in 5.3. A closure is good when you want a local function that's only used for some small, specific purpose. The RFC for closures give a good example:

function replace_spaces ($text) {
    $replacement = function ($matches) {
        return str_replace ($matches[1], ' ', ' ').' ';
    };
    return preg_replace_callback ('/( +) /', $replacement, $text);
}

This lets you define the replacement function locally inside replace_spaces(), so that it's not:
1) Cluttering up the global namespace
2) Making people three years down the line wonder why there's a function defined globally that's only used inside one other function

It keeps things organized. Notice how the function itself has no name, it simply is defined and assigned as a reference to $replacement.

But remember, you have to wait for PHP 5.3 :)

You can also access variables outside it's scope into a closure using the keyword use. Consider this example.

// Set a multiplier  
 $multiplier = 3;

// Create a list of numbers  
 $numbers = array(1,2,3,4);

// Use array_walk to iterate  
 // through the list and multiply  
 array_walk($numbers, function($number) use($multiplier){  
 echo $number * $multiplier;  
 }); 

An excellent explanation is given here What are php lambdas and closures

Solution 2:

When you will need a function in the future which performs a task that you have decided upon now.

For example, if you read a config file and one of the parameters tells you that the hash_method for your algorithm is multiply rather than square, you can create a closure that will be used wherever you need to hash something.

The closure can be created in (for example) config_parser(); it creates a function called do_hash_method() using variables local to config_parser() (from the config file). Whenever do_hash_method() is called, it has access to variables in the local scope ofconfig_parser() even though it's not being called in that scope.

A hopefully good hypothetical example:

function config_parser()
{
    // Do some code here
    // $hash_method is in config_parser() local scope
    $hash_method = 'multiply';

    if ($hashing_enabled)
    {
        function do_hash_method($var)
        {
            // $hash_method is from the parent's local scope
            if ($hash_method == 'multiply')
                return $var * $var;
            else
                return $var ^ $var;
        }
    }
}


function hashme($val)
{
    // do_hash_method still knows about $hash_method
    // even though it's not in the local scope anymore
    $val = do_hash_method($val)
}

Solution 3:

Apart from the technical details, closures are a fundamental pre-requisite for a programming style known as function oriented programming. A closure is roughly used for the same thing as you use an object for in object oriented programming; It binds data (variables) together with some code (a function), that you can then pass around to somewhere else. As such, they impact on the way that you write programs or - if you don't change the way you write your programs - they don't have any impact at all.

In the context of PHP, they are a little odd, since PHP already is heavy on the class based, object oriented paradigm, as well as the older procedural one. Usually, languages that have closures, has full lexical scope. To maintain backwards compatibility, PHP is not going to get this, so that means that closures are going to be a little different here, than in other languages. I think we have yet to see exactly how they will be used.