A coworker recently asked me what the difference was, functionally, between PHP’s create_function() function and traditional closures that you might find in languages with first-class functions, like Ruby or JavaScript. You can pretty easily illustrate this with a couple of examples.

First, a bit about closures. The idea with closures is that you can cleanly and readably pass around a bit of logic as an object, and any references that that object makes to variables in the surrounding scope must persist until that object is done with them.

So here’s an example in JavaScript:

<script type="text/javascript">
function getGreeter(name)
{
    return function(salutation) {
        alert(salutation + ', ' + name);
    }
}

var greeter = getGreeter('Eddy');
greeter('Hello');   // Hello, Eddy
greeter('Howdy');   // Howdy, Eddy
greeter('Bonjour'); // Bonjour, Eddy
</script>

Here’s the closest equivalent in PHP:

<?php
$code = '$name, $salutation', 'print $salutation . ', ' . $name;';
$greeter = create_function($code);
$greeter('Eddy', 'Hello');
// etc.

And that’s a callback, not a closure. In JavaScript the garbage collector reclaims the memory used by the anonymous “greeter” function… but in PHP functions get declared and stay declared, so every time you call create_function(), you increase the memory usage.

It gets worse. This is basically what PHP does internally:

<?php
function create_function($args, $code)
{
    // create a random $functionName
    eval('function ' . $functionName . '($args){$code}');
    return $functionName;
}

Yeah, the entire thing is evaluated. So not only does it not get garbage collected, but it has all the problems of eval()—it’s slow, difficult to debug, and uncacheable by bytecode caches like APC. Problems that closures don’t have in other languages.

It’s why you can do something like this…

<?php
$code = 'print "I print repeatedly.\n"; } print "I print once.\n"; if (false) {';
$function = create_function('', $code);
call_user_func($function);
call_user_func($function);
call_user_func($function);

// I print once.
// I print repeatedly.
// I print repeatedly.
// I print repeatedly.

…and why you should never use create_function().