13

If you want to use a closure from within a class, how do you pass in an instance variable from that class?

class Example {
    private $myVar;
    public function test() {
        $this->myVar = 5;
        $func = function() use ($this->myVar) { echo 'myVar is: ' . $this->myVar; };

        // The next line is for example purposes only if you want to run this code.
        // $func is actually passed as a callback to a library, so I don't have
        // control over the actual call.
        $func();
    }
}
$e = new Example();
$e->test();

PHP doesn't like this syntax:

PHP Fatal error:  Cannot use $this as lexical variable in example.php on line 5

If you take off $this-> then it can't find the variable:

PHP Notice:  Undefined variable: myVar in example.php on line 5

If you use use (xxx as $blah) as suggested in some places, it seems invalid syntax whether you have $this or not:

PHP Parse error:  syntax error, unexpected 'as' (T_AS), expecting ',' or ')' in example.php on line 5

Is there a way to do this? The only way I can get it to work is with a dodgy workaround:

$x = $this->myVar;
... function() use ($x) { ...
6
  • Your "workaround" at the end is how I would do it. Commented May 23, 2014 at 1:24
  • Why do you think it's dodgy? As it says, you can't use $this as a lexical variable, so you need to use another variable. That's what $x is. Commented May 23, 2014 at 1:25
  • It's dodgy because it adds an extra copy operation. I have to copy the variable into $x, then $x gets copied a second time into the closure. If I could do something like function () use ($this->myVar as $x) then it would avoid that extra copy and make the code neater. Commented May 23, 2014 at 1:27
  • PHP uses lazy copying, it initially just uses references, copying only when one of them is modified. Commented May 23, 2014 at 1:33
  • 2
    FWIW, PHP 5.4 supports $this inside closures. Commented May 23, 2014 at 1:50

3 Answers 3

13

If you are using PHP 5.4 or later, then you can use $this directly inside the closure:

$func = function() {
  echo 'myVar is: ' . $this->myVar;
};
Sign up to request clarification or add additional context in comments.

1 Comment

It looks like this also includes the parent:: variable in addition to $this, to access the parent class of the object $this (if there is one).
13

You can use your workaround. You can also be more general:

$self = $this;
$func = function() use ($self) {
    echo "myVar = " . $self->myVar;
};

Within the closure you can access any public properties or methods using $self instead of $this.

But it won't work for the original question, because the variable in question is private.

2 Comments

voodoo417 makes a good point - this will only work with public variables, not private ones.
Didn't think of that. I've updated my answer to reflect this limitation.
2

Why not ?:

    $func = function($param){ echo 'myVar is: ' . $param; };
    $func($this->myVar);

Update:

@Bramar right. But, if only $myVar will be public, it will work. Closures have no associated scope , so they cannot access private and protected members. In you specific case, you can do:

    $this->myVar = 5;   
    $_var = $this->myVar;
    $func = function() use ($_var) { echo 'myVar is: ' . $_var; };
    $func();

1 Comment

Sorry, $func() was just for example purposes. I am really passing this function to a library as a callback, so I have no control over the actual calling of my function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.