Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the use keyword in PHP closures pass by reference?

For example, if I do this:

function bar(&$var)
{
    $foo = function() use ($var)
    {
        $var++;
    };
    $foo();
}

$my_var = 0;
bar($my_var);

Will $my_var be modified? If not, how do I get this to work without adding a parameter to $foo?

like image 231
elite5472 Avatar asked Jun 03 '12 10:06

elite5472


People also ask

Is PHP function pass by reference?

Introduction. In PHP, arguments to a function can be passed by value or passed by reference. By default, values of actual arguments are passed by value to formal arguments which become local variables inside the function. Hence, modification to these variables doesn't change value of actual argument variable.

Which symbol is used when function argument is passed by reference in PHP?

Pass by reference: When variables are passed by reference, use & (ampersand) symbol need to be added before variable argument. For example: function( &$x ).

What is closure in PHP and why does it use use identifier?

A closure is a separate namespace, normally, you can not access variables defined outside of this namespace. There comes the use keyword: use allows you to access (use) the succeeding variables inside the closure.

Does PHP pass arrays by reference?

With regards to your first question, the array is passed by reference UNLESS it is modified within the method / function you're calling. If you attempt to modify the array within the method / function, a copy of it is made first, and then only the copy is modified.


3 Answers

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.

like image 122
hakre Avatar answered Sep 21 '22 14:09

hakre


Closures are, almost by definition, closed by value, not by reference. You may "use by reference" by adding an & in the argument list:

function() use (&$var) 

This can be seen in example 3 in the anonymous functions manual page.

like image 41
Emil Vikström Avatar answered Sep 20 '22 14:09

Emil Vikström


No, they are not passed by reference.

function foo(&$var)
{
    $foo = function() use ($var)
    {
        $var++;
    };
    $foo();
}

$my_var = 0;
foo($my_var);
echo $my_var; // displays 0

function bar(&$var)
{
    $foo = function() use (&$var)
    {
        $var++;
    };
    $foo();
}

$my_var = 0;
bar($my_var);
echo $my_var; // displays 1
like image 27
Jeroen Avatar answered Sep 18 '22 14:09

Jeroen