43
$ php --version
PHP 5.5.4 (cli) (built: Sep 19 2013 17:10:06) 
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies

以下代码(类似于https://bugs.php.net/bug.php?id=49543中的示例):

class Foo
{
    public function bar()
    {
        return function() use ($this)
        {
            echo "in closure\n";
        };
    }
}

失败:

PHP Fatal error:  Cannot use $this as lexical variable

然而,根据 PHP 文档和 Rasmus Lerdorf 对该错误报告的评论,在 PHP 5.4 中添加了在匿名函数中使用 $this。我究竟做错了什么?

4

8 回答 8

62

因此,如果 $this 不是通过“use”关键字指定的,那么它似乎可以简单地使用。

以下与“条”相呼应:

class Foo
{
    private $foo = 'bar';

    public function bar()
    {
        return function()
        {
            echo $this->foo;
        };
    }
}

$bar = (new Foo)->bar();

$bar();

这是在 php-internals 邮件列表中报告的,显然是由于 5.3 不支持此功能:

http://marc.info/?l=php-internals&m=132592886711725

于 2013-10-17T17:25:17.827 回答
9

如果您在PHP 5.3中使用闭包Closure则将无法访问$this.

PHP 5.4中,添加了对 in 使用的$this支持Closures

于 2016-05-17T06:23:32.000 回答
8

我不知道你的实际问题的答案(即你为什么不能这样做),但我可以给你一个解决方法:使用$thisand use()that 的临时副本:

class Foo
{
    public function bar()
    {
        $that = $this;
        return function() use($that)
        {
            print_r($that);
        };
    }
}

我刚刚测试了它,这确实有效。

于 2013-10-17T16:32:08.070 回答
6

问题是不允许包含$this在语句中。use()

但是,如果您不包含它,那么它将正常工作。

所以问题不在于 use 语句是否存在,而在于语句中是否$this存在use

这应该有效(@see https://3v4l.org/smvPt):

class Foo{
    private $a;
    function getAnon(){
        $b = 1;
        return function() use ($b) { 
            echo $b;
            echo $this->a;
        };
    }
}

这不应该:

class Foo{
    private $a;
    function getAnon(){
        $b = 1;
        return function() use ($this, $b) { 
            echo $b;
            echo $this->a;
        };    
    }
}

我想本质上$this是隐式捕获的。

于 2014-08-11T22:02:51.853 回答
5

你可以使用这个:

class Foo
{
  public function bar()
  {
    $obj = $this;
    return function() use ($obj)
    {
        //$obj->DoStuff();
        echo "in closure\n";
    };
  }
 }
于 2018-08-27T02:55:24.773 回答
4

我知道,这是一个老问题,但也许谷歌的人发现了这个:

您收到错误的原因是,您不能在同一个闭包中使用已经定义的变量名作为词法变量。

由于在 PHP 5.5 及更高版本中您可以访问闭包内部,因此已存在$this同名变量。$this

这是另一个示例,您会收到相同的错误:

$item = "Test 1";
$myFnc = function($item) use ($item) {
    ...
}
$myFnc("Test 2");

如您所见,$item已经用作闭包参数,因此您不能使用它的词法变量。

于 2018-05-15T13:12:54.093 回答
3

这可能是一个错误,但$this无论如何显式绑定到函数是没有意义的,因为它是自动绑定的:

PHP文档

从 PHP 5.4.0 开始,当在类的上下文中声明时,当前类会自动绑定到它,从而使 $this 在函数范围内可用。

因此,在今天的 PHP 版本中抛出了致命错误:

从 PHP 7.1 开始,这些变量不得包含超全局变量、$this 或与参数同名的变量。

于 2017-11-10T21:35:06.083 回答
1

我正在使用 PHP 5.4.25,实际上我可以在闭包中使用类变量,也可以使用use如下所示的关键字:

class Foo
{
    private $_privateBar = 'private bar';
    protected $_protectedBar = 'protected bar';
    public $_publicBar = 'public bar';

    public function bar()
    {
        $prefix = 'I am a ';

        return function() use ($prefix) {
            echo $prefix . $this->_privateBar . "\n";
            echo $prefix . $this->_protectedBar . "\n";
            echo $prefix . $this->_publicBar . "\n";
        };
    }
}

$foo = new Foo();
$bar = $foo->bar();

$bar();

输出:

I am a private bar
I am a protected bar
I am a public bar
于 2014-07-11T10:18:27.280 回答