dynamic引用$这不应该工作,但它
根据有关variablesvariables的 PHP文档:
$这是一个不能dynamic引用的特殊variables
不过,至less在PHP的版本中,它似乎是错误的,我testing过(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注意:未定义variables:this
PHP致命错误:调用一个非对象的成员函数doSomething()。
请注意,语句{'th' . 'is'}
{'th' . 'is'}
已被评估: “未定义variables:this” 。
然而(这是最奇怪的事情),显式引用特殊variables$this
,修复在该方法之前或之后使用的所有dynamic引用。
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
的dynamic引用?
PHP使用我们称之为编译variables(CV)优化的概念。 这意味着我们不使用将variables名映射到其值的散列表,而是使用一个普通的数组和索引。 编译器知道哪个variables名称对应于哪个索引。 执行数组索引查找比使用散列表查找要快得多。
$this
variables也将以这种方式存储,其索引被特别记住为op_array->this_var
。 如果没有$this
使用被发现这个值保持未初始化在-1
。 将新的执行上下文推送到VM栈时,PHP将检查op_array->this_var
,如果不是-1
,则初始化$this
variables条目。
当访问一个variablesvariables时,PHP将遍历CV表并从中构造一个适当的符号散列表。 当然,它只会添加实际存在于CV表中的variables,所以如果它不包含$this
那么最终会得到一个未定义的variables查找。
现在考虑你的三种情况:
-
$this
和${"this"}
与PHP编译器相同(在这两种情况下编译时已知所有的variables名)。 - 由于PHP 5.x编译器尚未执行常量expression式折叠,因此它将无法检测到
${"th"."is"}
是否为$this
访问。 所以this_var
保持未初始化。 - 在最后一种情况下,您有一个简单的
$this
用法,因为这样的this_var
将被设置,并且也可以通过variablesvariables查找来访问。
请注意,PHP 7中的情况有所不同 – 我们将始终将this_var
设置为variablesvariables查找,因此间接$this
查找应始终工作。