Почему я не могу использовать $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. Что я делаю неправильно?
Ответы
Ответ 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 или переменные с тем же именем, что и параметр.