Does the Use Keyword in PHP Closures Pass by Reference

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) the refcount(?) 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 (from 0) 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



Leave a reply



Submit