2010-01-11 12 views
22

Mit PHP 5.3 Ich habe seltsame/nicht-intuitive Verhalten bei der Anwendung empty() auf dynamische Objekteigenschaften über die __get() Überladung Funktion abgerufen. Betrachten Sie das folgende Code-Snippet:PHP empty() auf __get Accessor

<?php 

class Test { 

    protected $_data= array(
    'id'=> 23, 
    'name'=> 'my string' 
); 

    function __get($k) { 
    return $this->_data[$k]; 
    } 

} 

$test= new Test(); 
var_dump("Accessing directly:"); 
var_dump($test->name); 
var_dump($test->id); 
var_dump(empty($test->name)); 
var_dump(empty($test->id)); 

var_dump("Accessing after variable assignment:"); 
$name= $test->name; 
$id= $test->id; 
var_dump($name); 
var_dump($id); 
var_dump(empty($name)); 
var_dump(empty($id)); 

?> 

Die Ausgabe dieser Funktion ist wie folgt. Vergleichen Sie die Ergebnisse der empty() Kontrollen der ersten und zweiten Ergebnismengen:

Set # 1, unerwartetes Ergebnis:

string(19) "Accessing directly:" 
string(9) "my string" 
int(23) 
bool(true) 
bool(true) 

Set Erwartet 1 # das gleiche wie Set # 2 zurückzukehren:

string(36) "Accessing after variable assignment:" 
string(9) "my string" 
int(23) 
bool(false) 
bool(false) 

Das ist wirklich verwirrend und nicht intuitiv. Die Objekteigenschaften geben nicht leere Zeichenfolgen aus, aber empty() betrachtet sie als leere Zeichenfolgen. Was ist denn hier los?

+2

Sieht in der Tat sehr merkwürdig aus. Meine einzige Annahme ist, dass Leerstelle(), die ein Sprachkonstrukt ist, irgendwie die Getterfunktion umgeht. Aber das wäre ein großer Fehler in meinem Verständnis - es muss eine bessere Erklärung geben. Interessiert zu sehen, was aufkommt. –

+0

interessanterweise gibt 'isset()' true zurück, wenn direkt zugegriffen wird. – nickf

+0

Alan Storm hat es richtig gemacht, es gibt eine __isset magische Funktion, die aufgerufen wird, wenn ein Mitglied durch leer() überprüft wird. –

Antwort

28

Basierend auf einer Lesung der empty ‚s Manpage und Kommentare (Strg-F für isset und/oder doppelten Unterstrichen), sieht es aus wie dieses Verhalten bekannt ist, und wenn Sie möchten, dass Ihre __set und __get Methoden und empty zu Spielen Sie nett zusammen, es gibt eine implizite Annahme, dass Sie auch eine magische Magie-Methode __isset implementieren.

Es ist ein wenig untuitiv und verwirrend, aber das passiert bei den meisten Meta-Programmierung, besonders in einem System wie PHP.

+0

Du schlägst mich um sechzig Sekunden. Ich denke, das löst die Frage, obwohl es sehr kontraintuitiv ist, dass die __asset magische Methode standardmäßig false zurückgibt. –

+0

also '__isset' wird aufgerufen, wenn Sie' empty() 'aufrufen, aber nicht, wenn Sie' isset() '?? – nickf

+2

Per dem Handbuch sollte aufgerufen werden, wenn beide Funktionen verwenden. Die Auswirkung dessen, was ich gelesen habe, ist, dass es kein definiertes Verhalten zum Aufrufen von isset oder leer mit magischen Methoden gibt, wenn es keine __isset-Funktion gibt. –

3

In diesem Beispiel ruft empty() die Überladungsfunktion __isset() auf, nicht die Überladungsfunktion __get(). Versuchen Sie dies:

class Test { 

    protected $_data= array(
    'id'=> 23, 
    'name'=> 'my string' 
); 

    function __get($k) { 
    return $this->_data[$k]; 
    } 

    function __isset($k) { 
    return isset($this->_data[$k]); 
    } 

}