2010-10-29 40 views
9

有沒有一種方法可以隱式地將頂級變量聲明爲全局用於閉包?PHP關閉和隱式全局變量作用域

例如,如果使用代碼如此:

$a = 0; //A TOP-LEVEL VARIABLE 

Alpha::create('myAlpha') 
    ->bind(DataSingleton::getInstance() 
     ->query('c') 
    ) 
    ->addBeta('myBeta', function($obj){ 
     $obj->bind(DataSingleton::getInstance() 
       ->query('d') 
      ) 
      ->addGamma('myGamma', function($obj){ 
       $obj->bind(DataSingleton::getInstance() 
         ->query('a') 
        ) 
        ->addDelta('myDelta', function($obj){ 
         $obj->bind(DataSingleton::getInstance() 
          ->query('b') 
         ); 
        }); 
      }) 
      ->addGamma('myGamma', function($obj){ 

       $a++; //OUT OF MY SCOPE 

       $obj->bind(DataSingleton::getInstance() 
         ->query('c') 
        ) 
        . 
        . 
        . 

的封閉件從一個方法稱爲例如:

public function __construct($name, $closure = null){ 
     $this->_name = $name; 
     is_callable($closure) ? $closure($this) : null; 
    } 

因此,在總結/ TL; DR,是有一種隱式地將變量聲明爲全局變量的方法,以便在不使用關鍵字global$GLOBALS超級全局變量的情況下在閉包中使用(或其他函數)。

我在另一個論壇開始這個話題我頻繁(http://www.vbforums.com/showthread.php?p=3905718#post3905718

回答

31

您必須聲明它們在閉包定義:

->addBeta('myBeta', function($obj) use ($a) { // ... 

否則,您必須使用global關鍵字。您必須爲使用$a的每次關閉執行此操作。

+7

請注意'use'只從父範圍繼承變量。在全局範圍中沒有定義閉包的情況下,您仍然必須使用'global'關鍵字。它應該適用於OP的場景。 – Gordon 2010-10-29 18:02:24

+0

嗯,我害怕它會'使用'。希望這個問題在我正在開發的系統中不會流行,因爲大多數*全局*調用都可能用於靜態實例。我試圖在'$ GLOBALS'和'call_user_func_array()'中調用'extract()'的技巧...... – Dan 2010-10-29 18:09:41

+5

另外,OP的例子中顯示的'$ a ++'不會被應用回全局'$ a',除非它被引用使用,例如'&$ a'。對象雖然用於參考。 – Gordon 2010-10-29 18:10:18