【问题标题】:PHP closures and implicit global variable scopePHP 闭包和隐式全局变量作用域
【发布时间】: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) 上开始了这个话题

【问题讨论】:

    标签: php scope closures global-variables anonymous-function


    【解决方案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);,这将起作用。不过,我可以看到使用这种策略时性能会受到严重影响。
    猜你喜欢
    • 2017-06-21
    • 2013-09-08
    • 2016-10-11
    • 2013-03-13
    • 2023-03-04
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多