John Sonderson
John Sonderson

Reputation: 3388

PHP closure: use keyword with function definition: object argument to use: parameter not copied

The following code is a slightly modified version of an example from

PHP Manual -> Language Reference -> Functions -> Anonymous functions.

The example mentions, but doesn't explain, why you cannot pass a PHP object by value to the argument list after the use keyword in a function. In paricular, why isn't the object passed by value in the use parameter list as in the following code copied inside the $broken anonymous function just like can be done with scalar values?

Here is the code:

class MyClass {

  function doSomething() { echo "HELLO WORLD\n"; }

}

$myInstance = null;

$broken = function() use ($myInstance) {
    if(!empty($myInstance)) $myInstance->doSomething();
    else echo "\$myInstance is empty.\n";
    var_dump($myInstance); // NULL
};

$working = function() use (&$myInstance) {
    if(!empty($myInstance)) $myInstance->doSomething();
    else print "\$myInstance is empty.\n";
};

$myInstance = new MyClass();

$myInstance->doSomething();    // Outputs HELLO WORLD.
$broken();                     // Outputs $myInstance is empty. NULL
$working();                    // Outputs HELLO WORLD.

Thanks.


This is an update to my post following the reply I received from Valentin Rodygin. If the $myInstance = null; line is commented out I get the following error:

Notice: Undefined variable: myInstance in C:\xampp\htdocs\myexamples\use.php on line 11

Basically, when the parameter to the use keyword is passed by value it is copied at the time the function that makes use of the use keyword is defined, not when the function that makes use of the use keyword is called. The same is true for variables which are passed by reference, but since they are passed by reference, any later modification to such variable prior to invoking the function will make the updated value of such a variable available inside the function.

Thanks.

Upvotes: 1

Views: 194

Answers (1)

Valentin Rodygin
Valentin Rodygin

Reputation: 864

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.

Upvotes: 2

Related Questions