How many times did you worked with tools that you didn't designed ? Hard to count isn't? Sometimes using PHP libraries that are very complex and at the same time don't cover all the requirements that you have, you will have problems trying to cover such requirements. A closure is a separate namespace where normally, you can't access variables defined outside of this namespace. That's where comes the use keyword that makes the variable from outside the scope available inside the closure e.g:
<?php
function some_function_that_expect_closures($callback){
if (is_callable($callback)) {
$returnValue = call_user_func($callback);
}
return $returnValue;
}
$variableOutside = array(
"a" => 1,
"b" => 2
);
$returnedValue = some_function_that_expect_closures(function() use ($variableOutside){
// array(2) { ["a"]=> int(1) ["b"]=> int(2) }
var_dump($variableOutside);
return "Hello World";
});
// string(11) "Hello World"
var_dump($returnedValue);
One of the most common problems with libraries that use closures, is that beginner developers are unable to update the value of a variable from outside the scope of the PHP closure, for example:
<?php
function libraryWithCallback($callback){
if (is_callable($callback)) {
$argument = "cheese";
$returnValue = call_user_func($callback, $argument);
}
}
$myVariable = "nachos";
libraryWithCallback(function($newValue) use ($myVariable){
// Assign "cheese" tovariable
$myVariable = $newValue;
});
// Prints "nachos"
echo $myVariable;
The goal of the previous snippet is to simply change the value of $myVariable
through a callback function (closure). A beginner in PHP would simply think that the value of $myVariable
is now "cheese", however it isn't due to the way that closures work.
Changing value of a variable within a closure
So simply as it sounds, you can change the value of a variable outside a closure by passing it as a reference and not a copy (making the variable available inside the closure) prepending &
to the variable in the use statement. As shown in the official documentation of PHP, the syntax to pass a variable by reference is the following:
<?php
function foo(&$var)
{
$var++;
}
$a = 5;
foo($a);
// $a is 6 here
So in our example inside closures, you could just simply update the value of a variable outside making it available inside the scope with use and passing it by reference prepending &
to the variable:
<?php
function libraryWithCallback($callback){
if (is_callable($callback)) {
$argument = "cheese";
$returnValue = call_user_func($callback, $argument);
}
}
$myVariable = "nachos";
libraryWithCallback(function($newValue) use (&$myVariable){
// Assign "cheese" tovariable
$myVariable = $newValue;
});
// Prints "cheese"
echo $myVariable;
Note that you can assign any value (not only scalar values) without a problem within the closure.
Happy coding !