34

トランザクションをログに記録する汚い作業を行う関数を作成したいのですが、無名関数スコープが親スコープ$db$value変数を登録していないようです。変数をクロージャーに渡すにはどうすればよいですか?

皮肉なことに、SOタグの「クロージャ」はPHPバージョンを正確に記述していません...?

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

2 に答える 2

69

キーワードを使用して、use変数を関数のスコープにバインドします。

function() use ($db) {

クロージャは、親スコープから変数を継承する場合もあります。useこのような変数はすべて、[using ]関数ヘッダーで宣言する必要があります。

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

于 2013-02-23T15:35:21.807 に答える
1

PHP 8.0以降、矢印関数が使用可能になりました。これらは、宣言なしで親スコープから変数を継承します。

矢印関数は、親スコープからの変数の使用が常に自動であることを除いて、無名関数と同じ機能をサポートします。

これらは単一の式での使用を目的としているため、問題のコードには理想的ではありませんが、そのうちの2つを使用すると機能します。

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));
    }
}
于 2021-06-25T18:59:47.287 に答える