Динамически ссылка на $это не должно работать, но это делает
согласно документации PHP о переменные:
$это специальная переменная, на которую нельзя ссылаться динамически
однако кажется, что это ложь, по крайней мере, на версии PHP, которую я тестировал (5.5.12).
class ThisIsBugged
{
public function __construct()
{
${'this'}->doSomething(); // This works, while it shouldn't
}
}
Вопрос № 1: как это может работать? Согласно документации этого делать не следует.
но это еще не все.
class ThisIsBugged
{
public function __construct()
{
// This does not work, but it could. See below.
${'th' . 'is'}->doSomething();
}
}
это останавливает исполнение как ожидалось:
PHP Примечание: неопределенная переменная: this
PHP фатальная ошибка: вызов функции-члена doSomething () на a не-объект.
обратите внимание, что заявление {'th' . 'is'}
была оценена: "неопределенная переменная: этот".
однако (это самое странное), явно ссылаясь на специальной переменной $this
, исправляет все динамические ссылки, используемые до или после этого в метод.
class ThisIsBugged
{
public function __construct()
{
// Now it works while it shouldn't
${'th' . 'is'}->doSomething();
// This fixes both the previous and the subsequent calls
$unused = $this;
// Now it works while it shouldn't
${'th' . 'is'}->doSomething();
}
}
Вопрос № 2: как явная ссылка на $this
можно исправить все другие динамические ссылки на $this
присутствует во всем методе?
1 ответ:
PHP использует концепцию, которую мы называем оптимизацией скомпилированных переменных (CV). Это означает, что вместо использования хэш-таблицы, которая сопоставляет имена переменных с их значениями, мы используем простой массив и индекс в него. Компилятор знает, какое имя переменной соответствует какому индексу. Поиск индекса массива выполняется значительно быстрее, чем поиск хэш-таблиц.
The
$this
переменная также будет храниться таким образом, и ее индекс специально запоминается какop_array->this_var
. Если нет$this
использование найдено это значение остается неинициализированным в-1
. При нажатии нового контекста выполнения на стек виртуальной машины PHP будет проверятьop_array->this_var
и, если это не так-1
инициализации$this
переменной записи.когда переменная переменная доступна, PHP пройдет через таблицу CV и построит из нее правильную хэш-таблицу символов. Конечно, он будет добавлять только переменные, которые на самом деле находятся в таблице CV, так что если он не содержит
$this
вы будете в конечном итоге с неопределенной переменной уважать.теперь рассмотрим ваши три случая:
$this
и${"this"}
то же самое, что касается компилятора PHP (ведь имя переменной известно во время компиляции в обоих случаях).- как PHP 5.компилятор x еще не выполняет свертку константных выражений, однако он не сможет обнаружить, что
${"th"."is"}
это$this
открыть, а также. Так чтоthis_var
остается неинициализированным.- в последнем случае у вас есть простой
$this
использование, как таковыхthis_var
будет установлен, а также доступны через переменную-переменная поиска.обратите внимание, что в PHP 7 ситуация другая-мы всегда будем устанавливать
this_var
на переменную переменную поиска, так косвенно$this
поиск должен работать всегда.