0

I just noticed that if you try to put a variable variable into a use list of a closure, it throws a parse error. Example code:

foreach ($array as $key => $item) {
    $$key = $item->something;
    $this->doSomething($key, function ($param) use ($item, $$key) {
        $param->foo($$key);
    });
}

The parse error is this:

Parse error: syntax error, unexpected '$', expecting '&' or variable (T_VARIABLE) in

Is there something I'm doing wrong here? Why wont it let me pass the variable variable?

If I store the variable variable's value in another variable, I can pass it normally through use, but that's not optimal for my actual case.

aborted
  • 4,481
  • 14
  • 69
  • 132

1 Answers1

1

You say you don't want to save the value in another variable. But what about saving a reference to the variable? That should be functionally equivalent to your code.

foreach ($array as $key => $item) {
    $$key = $item->something;
    $otherVar = &$$key;
    $this->doSomething($key, function ($param) use ($item, $otherVar) {
        $param->foo($otherVar);
    });
}

If this doesn't work in "your actual case", please refine the code example or explain why.

Anders Carstensen
  • 2,949
  • 23
  • 23
  • Yeah this workaround is great, but I wanted to make sure that my problem is actually to be expected or if it's just me messing something up. Why doesn't PHP allow passing variable variables like that? – aborted Dec 25 '18 at 19:06
  • 1
    @Dugi you got bitten by PHP's years of adaptative syntax. Years and years of hackish partly-implemented things (like variable-invariable syntax, i.e. `$$`). This solution is the closest you'll get and it's one extra allocation in total. – Sébastien Renauld Dec 25 '18 at 19:07
  • @Dugi I can only come with an educated guess: If you were allowed to pass `$$key` in the `use` statement, you could just change `$key` in the function body, effectively making all variables outside of the function body available inside. That would undermine the principles of scopes. – Anders Carstensen Dec 25 '18 at 19:19