Does the use keyword in PHP closures pass by reference?
No, they are not passed by reference - the use
follows a similar notation like the function's parameters.
As written you achieve that by defining the use
as pass-by-reference:
$foo = function() use (&$var)
It's also possible to create recursion this way:
$func = NULL;
$func = function () use (&$func) {
$func();
}
NOTE: The following old excerpt of the answer (Jun 2012) was written for PHP < 7.0. As since 7.0 (Dec 2015) the semantics of
debug_zval_dump()
changed (different zval handling) therefcount(?)
output of it differs nowadays and are not that much saying any longer (integers don't have a refcount any longer).Validation via the output by not displaying
$my_var
changed (from0
) still works though (behaviour).
You can validate that on your own with the help of the debug_zval_dump
function (Demo):
function bar(&$var)
{
$foo = function() use ($var)
{
debug_zval_dump($var);
$var++;
};
$foo();
};
$my_var = 0;
bar($my_var);
echo $my_var;
Output:
long(0) refcount(3)
0
A full-through-all-scopes-working reference would have a refcount of 1.
Use keyword in functions - PHP
The use of "use" is correct in this case too.
With closures, to access variables that are outside of the context of the function you need to explicitly grant permission to the function using the use function. What it means in this case is that you're granting the function access to the $tax and $total variables.
You'll noticed that $tax was passed as a parameter of the getTotal function while $total was set just above the line where the closure is defined.
Another thing to point out is that $tax is passed as a copy while $total is passed by reference (by appending the & sign in front). Passing by reference allows the closure to modify the value of the variable. Any changes to the value of $tax in this case will only be effective within the closure while the real value of $total.
In PHP, what is a closure and why does it use the use identifier?
This is how PHP expresses a closure. This is not evil at all and in fact it is quite powerful and useful.
Basically what this means is that you are allowing the anonymous function to "capture" local variables (in this case, $tax
and a reference to $total
) outside of it scope and preserve their values (or in the case of $total
the reference to $total
itself) as state within the anonymous function itself.
php closure in anonymous function and reference &
Anonymous functions are actually Closure
objects in php. If you add var_dump($invoke)
to your code, you'll see this:
object(Closure)#1 (1) {
["static"]=>
array(2) {
["limit"]=>
int(2)
["tally"]=>
int(0)
}
}
use
'd variables are stored in the static
array in the closure object. When you invoke the closure, these variables are passed to the function, just like normal arguments. Therefore, if you don't use a reference, they will be passed by copying and any changes to them in the function will have no effect.
What's the difference between closure parameters and the 'use' keyword?
A closure is a function that is evaluated in its own environment, which has one or more bound variables that can be accessed when the function is called. They come from the functional programming world, where there are a number of concepts in play. Closures are like lambda functions, but smarter in the sense that they have the ability to interact with variables from the outside environment of where the closure is defined.
The use() keyword let's you import variables from outside the function environment, inside the function. Variables to be imported from the outside environment are specified in the use clause of the closure function definition. By default, they are passed by value. So let's say the function has no parameters, but you wan't it to use a variable you already have.
$string = "Hello World!";
$closure = function() use ($string) { echo $string; };
This is useful when you need to create a function what must be used as callback somewhere else, and can only have defined parameters. The use() keyword let's you use other variables in addition to the ones you pass as function arguements. For example on the php.net example: http://php.net/manual/en/functions.anonymous.php
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
$callback must only have two parameters, because array_walk will only allow that much:
Typically, funcname takes on two parameters. The array parameter's
value being the first, and the key/index second.
So what can we do? We call use()
to add other variables that are not the $callback's scope, but in scope of the environment it is being called in.
PHP closure: use keyword with function definition: object argument to use: parameter not copied
Let's take a closer look at your code.
$myInstance = null;
$broken = function() use ($myInstance) {
if(!empty($myInstance)) $myInstance->doSomething();
else echo "\$myInstance is empty.\n";
var_dump($myInstance); // NULL
};
At this moment, you've already created a closure and passed there a copy of the variable and it's NULL.
$working = function() use (&$myInstance) {
if(!empty($myInstance)) $myInstance->doSomething();
else print "\$myInstance is empty.\n";
};
And here you passed a reference, so later, when you've instantiated $myInstance, it became accessible in the closure.
Is the 'use' keyword available for function closures pre 5.3?
Closures are introduced in 5.3, thus use
in conjunction with closures are also available in 5.3 or later (of course).
As an added bonus, how would you code around not being able to use 'use' within a closure
I don't understand the question completely, but because both closures and use
with closures comes with the same version, there is no situation, where you can not use use
with closures. Either both, or nothing (--> <5.3)
http://php.net/functions.anonymous
Release Notes 5.3.0
Related Topics
Count Word Frequency in a Text
How to Allow a User to Download a File Which Is Stored Outside of the Webroot
PHP HTML Decoding Help - Converting: a 'Quote' Is <B>Bold</B>
Model->Save() Not Working in Yii2
Problems with Secure Bind to Active Directory Using PHP
How to Execute MySQL Script with Variables Using PHP::Pdo
PHP Making a Download Counter Without Leaving the Current Page
Why Are My PHP Tags Converted to HTML Comments
Attach Image to Facebook Event (PHP Sdk, Rest or Graph API)
Mysql: Get Total in Last Row of MySQL Result
Selecting Rows Where a Field Is Null Using PHP Pdo Prepared Statements and MySQL
Upload Images Through PHP Using Unique File Names
Adjusting Time Zone in PHP with Datetime/Datetimezone
What Is the Rfc Compliant and Working Regular Expression to Check If a String Is a Valid Url