14

I'm a little confused with PHP closures. Can someone clear this up for me:

// Sample PHP closure
my_method(function($apples) use ($oranges) {
    // Do something here
});

What's the difference between $apples and $oranges and when should I be using each?

Peyman Mohamadpour
  • 17,954
  • 24
  • 89
  • 100
enchance
  • 29,075
  • 35
  • 87
  • 127
  • Possible duplicate of [In PHP 5.3.0, what is the function "use" identifier?](http://stackoverflow.com/questions/1065188/in-php-5-3-0-what-is-the-function-use-identifier) – Peyman Mohamadpour Jan 01 '17 at 08:31

2 Answers2

16

$apples will take on the value that is passed to the function when it is called, e.g.

function my_method($callback) {
    // inside the callback, $apples will have the value "foo"
    $callback('foo'); 
}

$oranges will refer to the value of the variable $oranges which exists in the scope where you defined the closure. E.g.:

$oranges = 'bar';

my_method(function($apples) use ($oranges) {
    // $oranges will be "bar"
    // $apples will be "foo" (assuming the previous example)
});

The differences is that $oranges is bound when the function is defined and $apples is bound when the function is called.


Closures let you access variables defined outside of the function, but you have to explicitly tell PHP which variables should be accessible. This is similar (but not equivalent!) to using the global keyword if the variable is defined in global scope:

$oranges = 'bar';

my_method(function($apples) {
    global $oranges;
    // $oranges will be "bar"
    // $apples will be "foo" (assuming the previous example)
});

The differences between using closures and global:

  • You can bind local variables to closures, global only works with global variables.
  • Closures bind the value of the variable at the time the closure was defined. Changes to the variables after the function was defined does not effect it.
    On the other hand, if you use global, you will receive the value the variable has at the moment when the function is called.

    Example:

    $foo = 'bar';
    $closure = function() use ($foo) { 
        echo $foo; 
    };
    $global = function() {
        global $foo;
        echo $foo;
    };
    
    $foo = 42;
    $closure(); // echos "bar"
    $global(); // echos 42
    
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • How is it different from using `global` because that's the first thing which came to mind. – enchance Sep 04 '13 at 14:20
  • @enchance: Because `use` can access variables in a local scope. When you do `use ($oranges)`, `$oranges` doesn't need to be global like it does when you do `global $oranges;`. – gen_Eric Sep 04 '13 at 14:21
  • 1
    `global` **is not** equivalent of `use` since `global` will refer to pure global context (also represented by `$GLOBALS`) while `use` will pass only current, local context. – Alma Do Sep 04 '13 at 14:23
  • @AlmaDoMundo: Exactly, that's why I said it is not equivalent. – Felix Kling Sep 04 '13 at 14:27
  • @enchance: Added an explanation. – Felix Kling Sep 04 '13 at 14:31
  • when `$foo` gets changed inside the `function()` it does not affect the value `$foo` has outside of it right? – Daniel W. Sep 04 '13 at 14:32
  • But passing by reference is possible? `function() use (&$foo) { }` ? – Daniel W. Sep 04 '13 at 14:35
  • @FelixKling: I see, so for closures having a `use` relies on *when* the closure was declared. That's a huge difference from `global`. – enchance Sep 04 '13 at 14:36
  • @DanFromGermany: It seems so. And assigning a value seems to work as expected. – Felix Kling Sep 04 '13 at 14:37
  • @enchance: Sometimes you cannot control *when* and *how* a function is called, e.g. when you pass it as callback to some third party code. You might still need access to value defined outside of the function, and that's what closures solve. Does that help? – Felix Kling Sep 04 '13 at 15:04
  • I am confused why did you commented on [What use keyword do in closures in php](http://stackoverflow.com/questions/10478596/what-use-keyword-do-in-closures-in-php) as a duplicate (possible duplicate of [In Php 5.3.0 what is the Function "Use" Identifier ? Should a sane programmer use it?](http://stackoverflow.com/questions/1065188/in-php-5-3-0-what-is-the-function-use-identifier) – Felix Kling May 7 '12 at 8:00), but answered this one a few months later! – Peyman Mohamadpour Jan 01 '17 at 08:36
  • @Trix I honestly don't remember why I did that, sorry. It was more than four years ago. – Felix Kling Jan 01 '17 at 08:48
3

$apples is passed as an argument to my_method, and $oranges is injected inside.

Farkie
  • 3,307
  • 2
  • 22
  • 33