为什么我不能在PHP 5.5.4中使用$ this作为词法变量?

时间:2013-10-17 15:50:25

标签: php

$ 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。我做错了什么?

8 个答案:

答案 0 :(得分:54)

所以看起来$如果没有通过“use”关键字指定,可以使用它。

以下回声'bar':

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

答案 1 :(得分:8)

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

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

我刚试过它,这确实有效。

答案 2 :(得分:7)

PHP 5.3中,如果您使用 Closure,则Closure将无法访问$this

PHP 5.4中,添加了对$thisClosures的使用的支持。

答案 3 :(得分:4)

问题是不允许在use()语句中包含$ this。但是,如果你不包含它,那么它将正常工作。

所以问题不在于是否存在使用声明,而是在使用声明中是否存在$ this。

这应该有效:

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;
        }
    }
}

我认为基本上$这是隐含的。

答案 4 :(得分:2)

这可能是一个错误,但是在函数显式绑定$this时没有任何意义,因为它自动绑定:

PHP documentation

  

从PHP 5.4.0开始,当在类的上下文中声明时,当前   class自动绑定到它,使得$ this在里面可用   功能的范围。

因此,今天的PHP版本中会出现致命错误:

  

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

答案 5 :(得分:2)

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

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

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

这是另一个例子,你会得到同样的错误:

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

正如您所看到的,$item已被用作闭包参数,因此您可以将它作为词汇变量。

答案 6 :(得分: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

答案 7 :(得分:1)

您可以使用此:

class Foo
{
  public function bar()
  {
    $obj = $this;
    return function() use ($obj)
    {
        //$obj->DoStuff();
        echo "in closure\n";
    };
  }
 }