Подтвердить что ты не робот

Почему я не могу использовать $this как лексическую переменную в PHP 5.5.4?

$ 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, использование $this в анонимных функциях было добавлено с PHP 5.4. Что я делаю неправильно?

4b9b3361

Ответ 1

Итак, кажется, что $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

Ответ 2

Я не знаю ответа на ваш реальный вопрос (т.е. Почему не может это сделать), но я могу дать вам работу: используйте временную копию $this и use(), а вместо этого:

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

Я только что протестировал его, и это работает.

Ответ 3

В PHP 5.3, если вы используете Closure внутри класса, Closure не будет иметь доступа к $this.

В PHP 5.4 добавлена ​​поддержка для использования $this в Closures.

Ответ 4

Проблема заключается в том, что включение $this в оператор use() не допускается. Однако, если вы не включите его, он будет работать нормально.

Таким образом, проблема заключается не в том, присутствует ли оператор use, а в том, существует ли $this в инструкции use.

Это должно работать:

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

Я предполагаю, что в основном $это неявно зафиксировано.

Ответ 5

Я использую 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

Ответ 6

Это может быть ошибка, но нет смысла в явной привязке $this к функции в любом случае, поскольку она автоматически связана:

Документация по PHP говорит

Как и в случае с PHP 5.4.0, если объявлено в контексте класса, текущий класс автоматически привязан к нему, делая $this доступным внутри область действия.

Таким образом, фатальная ошибка возникает в сегодняшней версии PHP:

Из PHP 7.1 эти переменные не должны включать суперглобалы, $this или переменные с тем же именем, что и параметр.