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 调用可能会针对静态实例进行。我正在尝试在$GLOBALScall_user_func_array() 上摆弄一个涉及extract() 的技巧... 另外,$a++ 像 OP 的示例中所示不会应用回全局 $a,除非它通过引用使用,例如 &$a。对象是通过引用使用的。 感谢 rojocaGordon。我知道建议的方法,将use 与引用变量一起使用。我不知道use 只从父范围继承,这是很好的信息。还有其他选择吗?在每个闭包开始时调用extract($GLOBALS); 是可行的,但我确信这会产生太多开销。我想保留 为了使其正常工作,您必须将 [insert-hoop-to-jump-through] 降至最低。请记住,闭包总是从相同的方法调用。 我发现这篇文章 (htmlist.com/development/…) 提供了一种解决方法来扩展最终的 Closure 类。通过在函数字符串上调用eval() 之前的extract($GLOBALS);,这将起作用。不过,我可以看到使用这种策略时性能会受到严重影响。

以上是关于PHP 闭包和隐式全局变量作用域的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript从作用域到闭包

JavaScript从作用域到闭包

闭包作用域THISOOP

闭包作用域THISOOP

05-js讲义(闭包作用域)

JavaScript作用域闭包简述