Closures have been introduced in PHP 5.3 and their most important use is for callback functions. Basically a closure in PHP is a function that can be created without a specified name - an anonymous function. Here's a closure function created as the second parameter of array_walk()
. By specifying the $v
parameter as a reference one can modify each value in the original array through the closure function.
<?php
$array = array('Ruby', 'PHP', 'JavaScript', 'HTML');
array_walk($array, function(&$v, $k) {
$v = $v . ' - Programming Language';
});
print_r($array);
You can define a closure as the value of a variable with a normal assignment. For example, the snippet below will print out 'I am a closure'.
<?php
$var = function() {
return 'I am a ' . func_get_arg(0);
};
print_r($var('Closure'));
Don't forget to end the assignment with a semicolon just like you would do with any variable definition ... I always forget so I thought it would help if I mentioned this :).
One of the most confusing aspects for these anonymous functions in PHP is related to how closures can make use of variables from their immediate parent scope (not necessarily the global scope). This is done with the use
language construct so that the syntax looks like this: function() use ($variable) { /* code */ }
.
In the example below, the closure will use / inherit the value of $param
from its parent scope which is the scope of the sayHello()
function, NOT the global scope and therefor the script will output Hi, I am Michael!
.
<?php
$param = 'John!';
function sayHello()
{
$param = 'Michael!';
$func = function() use ($param)
{
echo 'Hi, I am ' . $param;
};
$func();
}
sayHello();
If we were to modify the value of $param
inside the closure this would not affect it's value inside the parent scope unless we would 'use a reference'. In the two examples below, one with $param
as a reference and one as a normal (copied) variable the results are different.
This prints 'I am Michael!'
because $param
is not modified in its parent scope. In other words, the only place where $param='Dave!'
is inside the closure.
<?php
$param = 'John!';
function sayHello()
{
$param = 'Michael!';
$func = function() use ($param)
{
$param = 'Dave!';
};
$func();
echo 'I am ' . $param; // prints I am Michael!
}
sayHello();
The code below will print 'I am Dave!'
because $param
is 'used' as a reference.
<?php
$param = 'John!';
function sayHello()
{
$param = 'Michael!';
$func = function() use (&$param)
{
$param = 'Dave!';
};
$func();
echo 'I am ' . $param; // prints I am Dave!
}
sayHello();