Bubble Foundry


PHP Closures

by Peter.

PHP 5.3 has added support for true anonymous functions and closures. Unfortunately, there are a few gotchas.

The main one is that no variables are automatically enclosed: you must specify the variables you want to enclose. So, this will cause an exception:

$a = 2;
$f = function($i) {
  return $i + $a;
}
$f(1); // -> PHP Parse error:  syntax error, unexpected T_VARIABLE

While this is the proper format:

$a = 2;
$f = function($i) use ($a) {
  return $i + $a;
}
$f(1); // -> 3

However, you can also cheat with global:

$a = 2;
$f = function($i) {
  global $a;
  return $i + $a;
}
$f(1); // -> 3

Also, classes that are in scope seem to get imported into the closure’s scope. I believe this is because the class isn’t actually copied into the closure but is instead looked up:

class C {
  static $a = 1;
}
$f = function($i) {
  return $i + C::$a;
}

While normally you would never want to abuse the scope, I guess there may be times when you do.

You can even pass enclosed values by reference:

$a = 2;
$f = function($i) use (&$a) {
  $a = $i;
}
$f(1);
$a == 1 // -> true

Interestingly, I also learned that you can’t mutate a function’s input value:

$f = function($i) {
  return $i++;
}
$f(1); // -> 1

This is also the case in Javascript. To be honest, I’m not sure why this is, since the parameter is not an enclosed variable. But there you go. I’m sure someone who knows more about closures than me can explain why this is.

PS I find the original closures RFC somewhat more useful than the main documentation.