Динамически ссылка на $это не должно работать, но это делает
согласно документации 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поиск должен работать всегда.