2010-01-11 8 views
22

Uso de PHP 5.3 Estoy experimentando un comportamiento extraño/no intuitivo al aplicar empty() a las propiedades de objeto dinámico captadas a través de la función de sobrecarga __get(). Tenga en cuenta el siguiente fragmento de código:PHP vacío() en __objeto de acceso

<?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)); 

?> 

La salida de esta función es la siguiente. Comparación de los resultados de las empty() cheques en el primer y segundo conjuntos de resultados:

Set # 1, resultado inesperado:

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

Esperando Set # 1 para volver el mismo que Set # 2:

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

Esto es realmente desconcertante y no intuitivo. Las propiedades del objeto imprimen cadenas no vacías pero empty() las considera cadenas vacías. ¿Que está pasando aqui?

+2

Parece muy extraño de hecho. Mi única opinión sobre esto es que empty(), al ser una construcción de lenguaje, de alguna manera pasa por alto la función getter. Pero eso sería un * enorme * error en mi comprensión, debe haber una mejor explicación. Interesado en ver qué surge. –

+0

curiosamente, 'isset()' devuelve verdadero al acceder directamente. – nickf

+0

Alan Storm lo hizo bien, hay una función de magia __isset que se llama cuando un miembro se marca con empty(). –

Respuesta

28

Sobre la base de una lectura de la empty 's página y comentarios manual (Ctrl-F para isset y/o guiones dobles), parece que esto se conoce el comportamiento, y si desea que sus __set y __get métodos y empty a jugar bien juntos, hay una suposición implícita de que implemente un método mágico __isset también.

Es un poco intuitivo y confuso, pero eso tiende a suceder con la meta-programación, especialmente en un sistema como PHP.

+0

Me ganaste por sesenta segundos :) Creo que esto resuelve la pregunta, aunque es muy contrario a la intuición que el método de magia __isset devuelva falso por defecto. –

+0

por lo que '__isset' se invoca cuando llamas' empty() 'pero no cuando llamas' isset() '?? – nickf

+2

Según el manual, __isset se debe invocar cuando se usa cualquiera de las funciones. La consecuencia de lo que he leído es que no hay un comportamiento definido para llamar a isset o vaciar con métodos mágicos cuando no hay una función __isset. –

3

En este ejemplo, empty() llama a la función de sobrecarga __isset(), no a la función de sobrecarga __get(). Pruebe esto:

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

}