2015-02-09 12 views
54

Per PHP-Dokumentation über Variable variables:

$this is a special variable that cannot be referenced dynamically

aber es scheint, dass es falsch ist, zumindest auf der PHP-Version, die ich getestet habe (5,5 .12).

class ThisIsBugged 
{ 
    public function __construct() 
    { 
     ${'this'}->doSomething(); // This works, while it shouldn't 
    } 
} 

Frage # 1: Wie kann es? Laut der Dokumentation sollte es nicht.

Aber es gibt noch mehr.

class ThisIsBugged 
{ 
    public function __construct() 
    { 
     // This does not work, but it could. See below. 
     ${'th' . 'is'}->doSomething(); 
    } 
} 

Es stoppt die Ausführung, wie erwartet:

PHP Notice: Undefined variable: this

PHP Fatal error: Call to a member function doSomething() on a non-object.

Beachten Sie, dass die Aussage {'th' . 'is'} bewertet worden: "Nicht definierte Variable: dieses".

Allerdings (dies ist das Seltsamste), indem explizit auf die spezielle Variable $this verwiesen wird, werden alle dynamischen Referenzen korrigiert, die davor oder danach in der Methode verwendet werden.

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(); 
    } 
} 

Frage # 2: Wie eine explizite Bezugnahme auf $this alle anderen dynamischen Verweise auf $this in der ganzen Methode beheben kann?

+0

AFAIK die Form '$ {}' ist veraltet (obwohl ich keinen Link habe, der dies angibt) die Zustände des Docus über die Verwendung von dynamischer Verwendung des '$ this 'nicht die' $ {this} 'oder' $ {'this'} 'Der PHP-Parser versteht die eckigen Klammern als eine Form der Verwendung einer Zeichenkette als Variable. Versuchen Sie, das gleiche ohne Thrakets zu tun und sehen Sie, was passiert. –

+21

Die '$ {}' Form ist nicht veraltet. – ircmaxell

Antwort

70

PHP verwendet ein Konzept, das wir die kompilierte Variablen (CV) -Optimierung nennen. Das bedeutet, dass wir anstelle einer Hashtabelle, die Variablennamen ihren Werten zuordnet, ein einfaches Array und einen Index verwenden. Der Compiler weiß, welcher Variablenname welchem ​​Index entspricht. Das Ausführen von Array-Index-Lookups ist wesentlich schneller als das Durchführen von Hash-Lookups.

Die Variable $this wird ebenfalls auf diese Weise gespeichert, und ihr Index wird speziell als op_array->this_var gespeichert. Wenn keine $this Verwendung gefunden wird, wird dieser Wert bei -1 nicht initialisiert. Wenn Sie einen neuen Ausführungskontext auf den VM-Stack schieben, prüft PHP und, wenn es nicht -1 ist, initialisieren Sie den Variableneintrag $this.

Wenn auf eine Variable zugegriffen wird, durchläuft PHP die CV-Tabelle und erstellt daraus eine passende Hash-Datei. Natürlich fügt es nur Variablen hinzu, die tatsächlich in der CV-Tabelle enthalten sind. Wenn es also keine $this enthält, erhalten Sie eine undefinierte Variablensuche.

Betrachten wir nun Ihre drei Fälle:

  1. $this und ${"this"} gleich sind, so weit das PHP Compiler angeht (nach all den Variablennamen bei der Kompilierung in beiden Fällen bekannt ist).
  2. Da der PHP 5.x-Compiler noch keine Faltung mit konstantem Ausdruck durchführt, kann er nicht erkennen, dass ${"th"."is"} auch ein $this-Zugriff ist. So bleibt this_var nicht initialisiert.
  3. Im letzten Fall haben Sie eine einfache $this Verwendung, als solche this_var wird gesetzt und auch durch eine Variable-Variablen-Lookup zugänglich.

Beachten Sie, dass sich die Situation in PHP 7 anders ist - wir setzen immer this_var auf eine Variable variable Lookup, so indirekte $this Lookups sollte immer funktionieren.

+0

NikiC, danke für deine einwandfreie Antwort. Um 100% richtig zu sein, sollte das Handbuch sagen, dass "$ dies eine spezielle Variable ist, die nicht IMMER dynamisch referenziert werden kann?" –

+0

PHP 7? Was passierte mit PHP 6? –

+4

@samyismyhero Ich mache alle meine Programmierung jetzt in PHP 11 ... – BrianHall

Verwandte Themen