kmdhrm
kmdhrm

Reputation: 535

PHP - Difference between 'use()' or 'global' to access a global variable in a closure?

Is there any kind of performance or other difference between following two cases of accessing a global variable in a closure:

Case 1:

$closure = function() use ($global_variable) {
  // Use $global_variable to do something.
}

Case 2:

$closure = function() {
  global $global_variable; 
  // Use $global_variable to do something.
}

Upvotes: 7

Views: 2436

Answers (3)

s3c
s3c

Reputation: 1851

Your title question has been well answered, so I'll skip that.

You pose a different question in the body though. Which has better performance?

I made a simple test that I tried in PHP Sandbox:

<?php
$bool = true;

$one = function() use ($bool) {
    return $bool;
};

$two = function() {
    global $bool;
    return $bool;
};

for ($power = 1; $power <= 10000000; $power *= 10) {
    
    echo "loops = {$power}\n";

    $before = microtime(true);
    for ($i=0 ; $i<20000 ; $i++)
        $one();
    $after = microtime(true);
    $timeOne = ($after-$before)/$i;
    echo "{$timeOne} sec/one\n";
    
    
    $before = microtime(true);
    for ($i=0 ; $i<20000 ; $i++)
        $two();
    $after = microtime(true);
    $timeTwo = ($after-$before)/$i;
    echo "{$timeTwo} sec/two\n";
    
    echo "Winner: " . ($timeOne > $timeTwo ? 'one' : 'two') . "\n\n";
}

And the results are very inconclusive:

loops = 1
6.2644481658936E-8 sec/one
5.6242942810059E-8 sec/two
Winner: one

loops = 10
5.4049491882324E-8 sec/one
4.9102306365967E-8 sec/two
Winner: one

loops = 100
5.1343441009521E-8 sec/one
5.4597854614258E-8 sec/two
Winner: two

loops = 1000
5.5849552154541E-8 sec/one
5.2559375762939E-8 sec/two
Winner: one

loops = 10000
5.6040287017822E-8 sec/one
5.3608417510986E-8 sec/two
Winner: one

loops = 100000
5.8901309967041E-8 sec/one
4.960298538208E-8 sec/two
Winner: one

loops = 1000000
6.2298774719238E-8 sec/one
6.9999694824219E-8 sec/two
Winner: two

loops = 10000000
8.3756446838379E-8 sec/one
5.9354305267334E-8 sec/two
Winner: one

Perhaps use if a bit faster than global, but you probably should make the decision on which to use based on that. It's all about the use-case (no pun intended).

You have more control with use which is parent-scoped, so it's probably your best bet in most cases, but if you really need a variable from global scope, the answer is obvious.

Also note, that you can use use with anonymous (lambda) functions only (like in my testing example). If you want to have the same functionality in normally defined functions, then you need to have the variable in question as function parameter, but referenced by pointer. Beware, it's not without caveat. If your function makes any changes to the referenced variable, these change won't be local to the function. Here's an example.

// ...
function three(&$var) {
    return $var;
}

Upvotes: 0

simon
simon

Reputation: 2946

There is an important difference between your two examples:

$global_variable = 1;

$closure = function() use ($global_variable) {
    return $global_variable; 
};

$closure2 = function() {
    global $global_variable;
    return $global_variable;
};

$global_variable = 99;

echo $closure();    // this will show 1
echo $closure2();   // this will show 99 

use takes the value of $global_variable during the definition of the closure while global takes the current value of $global_variable during execution.

global inherits variables from the global scope while use inherits them from the parent scope.

Upvotes: 24

Gectou4
Gectou4

Reputation: 217

Usekeyword are in parent scope, while global and $GLOBALS are from everywhere.

That's mean if you use global you may not know if the value have changed, from where by what and what is the kind of the change.

You have more control by using use. So it depends on your needs.

Upvotes: 1

Related Questions