PHP中匿名函数/闭包是否有词法作用域?

7

我正在使用PHP 5.4,想知道我所创建的匿名函数是否具有词法作用域?

例如,如果我有一个控制器方法:

protected function _pre() {
    $this->require = new Access_Factory(function($url) {
        $this->redirect($url);
    });
}

当Access Factory调用传递的函数时,$this会指向定义它的控制器吗?
2个回答

7

匿名函数不使用词法作用域,但是$this是一个特例,在5.4.0版本后将自动在函数内部可用。您的代码应该按预期工作,但它不适用于旧版本的PHP。


以下代码不会起作用:

protected function _pre() {
    $methodScopeVariable = 'whatever';
    $this->require = new Access_Factory(function($url) {
        echo $methodScopeVariable;
    });
}

如果你想将变量注入到闭包的作用域中,可以使用use关键字。以下代码将会起作用:

protected function _pre() {
    $methodScopeVariable = 'whatever';
    $this->require = new Access_Factory(function($url) use ($methodScopeVariable) {
        echo $methodScopeVariable;
    });
}

在5.3.x版本中,您可以使用以下方法访问$this
protected function _pre() {
    $controller = $this;
    $this->require = new Access_Factory(function($url) use ($controller) {
        $controller->redirect($url);
    });
}

有关更多详细信息,请参见此问题及其答案


啊,好知道 PHP5.4 中有所不同(它还没有到达我的 Debian Stable 软件包...可能需要手动安装)。 - Wrikken
我需要使用"use ($this)"吗?还是5.4版本会自动让你访问$this? - Charles
5.4.0+自动绑定$this。请查看这个简短的视频进行解释。 - Matt Kantor
当然它使用词法作用域。现今常见的编程语言都使用词法作用域。$this是一个特殊变量,具有特殊含义。 - newacct
2
@newacct:在PHP中,函数并不是按照我所熟悉的定义词法作用域。它们与周围的范围“隔离”,只能访问或影响自身、(超级)全局变量和 $this/self/parent(如果在类内定义),除非使用 use 显式地绑定额外的变量。请参见此演示。 - Matt Kantor
哎呀,选择性闭包!这是多么可怕的概念啊。PHP领域中应该有人被开除。 - Beetroot-Beetroot

1
简而言之,不行,但是你可以通过传递它来访问公共方法和函数:
$that = $this;
$this->require = new Access_Factory(function($url) use ($that) {
    $that->redirect($url);
});

编辑:正如Matt所指出的那样,PHP 5.4开始闭包中支持$this


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接