3

While learning about anonymous functions in PHP I came across this:

Anonymous functions can use the variables defined in their enclosing scope using the use syntax.

For example:

    $test = array("hello", "there", "what's up");
    $useRandom = "random";

    $result = usort($test, function($a, $b) use ($useRandom){

                                if($useRandom=="random")
                                    return rand(0,2) - 1;
                                else
                                    return strlen($a) - strlen($b);
                            } 
                    );

Why can't I just make $useRandom global like below?

    $test2 = array("hello", "there", "what's up");
    $useRandom = "random";

    $result = usort($test, function($a, $b){

                                global $useRandom;

                                if($useRandom=="random")
                                    return rand(0,2) - 1;
                                else
                                    return strlen($a) - strlen($b);
                            } 
                    );

What's the difference between these two approaches?

chris85
  • 23,846
  • 7
  • 34
  • 51
Hello Lili
  • 1,527
  • 1
  • 25
  • 50
  • 1
    You're passing in an argument on your first example, therefore `$useRandom` is *not* global. In your second example you make the variable global. – Jay Blanchard Sep 23 '15 at 12:49
  • 1
    `use` is still bound to the current scope. `global` is well `global` – PeeHaa Sep 23 '15 at 12:50
  • 3
    Certainly using `global` often works. but it still carries the well known problems, name collision between libraries for example. – arkascha Sep 23 '15 at 12:51
  • 2
    Note that in your second example, if you were to change `$useRandom` inside the anonymous function, it would change the value of the global, of course. In your first example, changing `$useRandom` inside the anonymous function would leave the value `$useRandom` outside the anonymous function unchanged. – Matt Gibson Sep 23 '15 at 12:56

2 Answers2

4

Your examples are a bit simplified. To get the difference try to wrap your example code into another function, thus creating an additional scope around the inner callback, that is not global.

In the following example $useRandom is always null in the sorting callback, since there is no global variable called $useRandom. You will need to use use to access a variable from an outer scope that is not the global scope.

function test()
{
    $test = array( "hello", "there", "what's up" );
    $useRandom = "random";

    $result = usort( $test, function ( $a, $b ) {

            global $useRandom;
            // isset( $useRandom ) == false

            if( $useRandom == "random" ) {
                return rand( 0, 2 ) - 1;
            }
            else {
                return strlen( $a ) - strlen( $b );
            }
        }
    );
}

test();

On the other hand, if there is a global variable $useRandom it can be accessed using use only one scope down. In the next example $useRandom is again null, since it was defined two scopes "higher" and the use keyword only imports variables from the scope directly outside the current scope.

$useRandom = "random";

function test()
{
    $test = array( "hello", "there", "what's up" );

    $result = usort( $test, function ( $a, $b ) use ( $useRandom ) {

            // isset( $useRandom ) == false

            if( $useRandom == "random" ) {
                return rand( 0, 2 ) - 1;
            }
            else {
                return strlen( $a ) - strlen( $b );
            }
        }
    );
}

test();
feeela
  • 29,399
  • 7
  • 59
  • 71
2

You have to be careful with globals for many reasons, not the least of which is unexpected behavior:

$foo = 'Am I a global?';

function testGlobal(){
    global $foo;
    echo $foo . ' Yes, I am.<br />';
}

function testAgain() {
    if(isset($foo)) {
        echo $foo . ' Yes, I am still global';
    } else {
        echo 'Global not available.<br />';
    }
}
testGlobal();
testAgain();

In this example you might expect that once you have made the variable global it would be available to subsequent functions. The result of running this code demonstrates that this is not the case:

Am I a global? Yes, I am.

Global not available.

Declaring a global in this way makes the variable available within the scope of its global declaration (in this case, the function testGlobal()), but not in the general scope of the script.

Check out this answer on Using Globals and why it is a bad idea.

Community
  • 1
  • 1
Jay Blanchard
  • 34,243
  • 16
  • 77
  • 119
  • Strange assumption. I can't even imagine that anyones thinks a variable imported to one function is also magically available in some other function. – feeela Sep 23 '15 at 13:03
  • 1
    I have seen this on more than one occasion, especially with new developers @feeela. They assume the variable, once declared `global` is available everywhere. – Jay Blanchard Sep 23 '15 at 13:04