2010-10-29 68 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