39

I want to write a function that does some dirty work logging a transaction, but the anonymous function scope does not seem to register the parent scope $db and $value variables. How can I pass the variables into the closure?

Ironically, the SO tag 'closures' does not describe the PHP version of it very accurately...?

class controller { function submit() { $db = new database(); $result = $db->execute_tx(function() { $db->insert_model_a($value_a); // ERROR: $db is non-object $db->insert_model_b($value_b); }); } } class database { function execute_tx($atomic_action) { try { $this->start(); $atomic_action(); $this->commit(); // etc.. } catch(...) { $this->rollback(); // etc.. } finally { // etc.. } } function insert_model_a() { ... } function insert_model_b() { ... } } 
0

2 Answers 2

76

Use the use keyword to bind variables into the function's scope.

function() use ($db) { 

Closures may also inherit variables from the parent scope. Any such variables must be declared in the function header [using use].

http://www.php.net/manual/en/functions.anonymous.php

Sign up to request clarification or add additional context in comments.

9 Comments

is this the ONLY way? Because I have like 10 to 15 values in some submit and I have many submits to go through...
Yes. You must explicitly import the variables that you want the closure to close over.
@Jake If you have a state of 10-15 values in that function, you're doing something wrong.
@Jack Why is that so? Why so certain?
This just ended 45 minutes of frustration. Wonderful.
|
3

Since PHP 8.0, arrow functions have been available. These inherit variables from the parent scope without any declarations:

Arrow functions support the same features as anonymous functions, except that using variables from the parent scope is always automatic.

They are intended for use with single expressions, so are not ideal for the code in the question, but using two of them would work:

class Controller { function submit() { $db = new database(); // one assumes $value_a and $value_b are defined in the submit method $result = $db->execute_tx(fn() => $db->insert_model_a($value_a)); $result = $db->execute_tx(fn() => $db->insert_model_b($value_b)); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.