PHP 闭包和隐式全局变量作用域
Posted
技术标签:
【中文标题】PHP 闭包和隐式全局变量作用域【英文标题】:PHP closures and implicit global variable scope 【发布时间】:2011-05-02 13:12:50 【问题描述】:有没有一种方法可以隐式将***变量声明为全局变量以在闭包中使用?
例如,如果使用这样的代码:
$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) 上开始了这个话题
【问题讨论】:
【参考方案1】:你必须在闭包定义中声明它们:
->addBeta('myBeta', function($obj) use ($a) // ...
否则您必须使用global
关键字。对于每个使用 $a
的闭包,您也必须这样做。
【讨论】:
请注意,use
仅从父作用域继承变量。在全局范围内未定义闭包的情况下,您仍然必须使用 global
关键字。不过,它应该适用于 OP 的场景。
嗯,我怕是use
。希望这个问题不会在我正在开发的系统中普遍存在,因为大多数 global 调用可能会针对静态实例进行。我正在尝试在$GLOBALS
和call_user_func_array()
上摆弄一个涉及extract()
的技巧...
另外,$a++
像 OP 的示例中所示不会应用回全局 $a
,除非它通过引用使用,例如 &$a
。对象是通过引用使用的。
感谢 rojoca 和 Gordon。我知道建议的方法,将use
与引用变量一起使用。我不知道use
只从父范围继承,这是很好的信息。还有其他选择吗?在每个闭包开始时调用extract($GLOBALS);
是可行的,但我确信这会产生太多开销。我想保留 为了使其正常工作,您必须将 [insert-hoop-to-jump-through] 降至最低。请记住,闭包总是从相同的方法调用。
我发现这篇文章 (htmlist.com/development/…) 提供了一种解决方法来扩展最终的 Closure 类。通过在函数字符串上调用eval()
之前的extract($GLOBALS);
,这将起作用。不过,我可以看到使用这种策略时性能会受到严重影响。以上是关于PHP 闭包和隐式全局变量作用域的主要内容,如果未能解决你的问题,请参考以下文章