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名称对应于哪个索引。 执行数组索引查找比使用散列表查找要快得多。

$thisvariables也将以这种方式存储,其索引被特别记住为op_array->this_var 。 如果没有$this使用被发现这个值保持未初始化在-1 。 将新的执行上下文推送到VM栈时,PHP将检查op_array->this_var ,如果不是-1 ,则初始化$thisvariables条目。

当访问一个variablesvariables时,PHP将遍历CV表并从中构造一个适当的符号散列表。 当然,它只会添加实际存在于CV表中的variables,所以如果它不包含$this那么最终会得到一个未定义的variables查找。

现在考虑你的三种情况:

  1. $this${"this"}与PHP编译器相同(在这两种情况下编译时已知所有的variables名)。
  2. 由于PHP 5.x编译器尚未执行常量expression式折叠,因此它将无法检测到${"th"."is"}是否为$this访问。 所以this_var保持未初始化。
  3. 在最后一种情况下,您有一个简单的$this用法,因为这样的this_var将被设置,并且也可以通过variablesvariables查找来访问。

请注意,PHP 7中的情况有所不同 – 我们将始终将this_var设置为variablesvariables查找,因此间接$this查找应始终工作。