Access variables from parent scope in anonymous PHP function

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() { ... }
}

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


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));
    }
}