2012-04-04 12 views
12

considerar esta clase:¿Cómo evita PHP recurrencia infinita aquí?

class test 
{ 
    public function __set($n, $v) 
    { 
     echo "__set() called\n"; 
     $this->other_set($n, $v, true); 
    } 

    public function other_set($name, $value) 
    { 
     echo "other_set() called\n";  
     $this->$name = $value; 
    } 

    public function t() 
    { 
     $this->t = true; 
    } 
} 

estoy sobrecarga de métodos magia __set() de PHP. Cada vez que establezco una propiedad en un objeto de la clase test, llamará al __set(), que a su vez llama al other_set().

$obj = new test; 
$test->prop = 10; 

/* prints the following */ 
__set() called 
other_set() called 

Pero other_set() tiene la siguiente línea $this->$name = $value. ¿No debería esto dar como resultado una llamada al __set(), causando recursión infinita?

Teoricé que llamaría a __set() solo cuando establezca cosas fuera de la clase. Pero si llama al método t(), puede ver claramente que también pasa por __set().

Respuesta

11

__set is only called once per attempt for a given property name. Si (o lo que se llame) intenta establecer la misma propiedad, PHP no llamará __set nuevamente - simplemente establecerá la propiedad en el objeto.

+0

Esto es correcto. Si alguien quiere ver los detalles de implementación, está en 'zend_object_handlers.c'. – Confluence

+0

@Confluence: Gracias ... me preguntaba dónde lo había leído. :) No pude encontrarlo en el manual; Estaba empezando a preguntarme si me lo había imaginado. Pero todas mis pruebas lo confirmaron, así que ... – cHao

+0

¡Esta respuesta fue TAN útil! –

2

Desde el documentation:

__set() se ejecuta al escribir datos en inaccesibles propiedades

Por ejemplo:

class foo { 
    private $attributes; 
    public $bar; 

    public function __construct() { 
    $this->attributes = array(); 
    } 

    public function __set($n, $v) { 
    echo "__set() called\n"; 
    $this->attributes[$n] = $v; 
    } 
} 

$x = new foo; 
$x->prop = "value"; 
$x->attributes = "value"; 
$x->bar = "hello world"; 

En este caso, $x->prop es inaccesible y __set se llamará. $x->attributes también es inaccesible, por lo que se llamará __set. Sin embargo, $x->bar es de acceso público, por lo que __set se no se llamará.

De manera similar, en el método __set, $this->attribtues es accesible, por lo que no hay recursividad.

En su código de ejemplo anterior, $this->$name está accesible en el ámbito en el que se llama, por lo tanto __set no se llama.

+0

¿Qué diferencia hace eso? – Confluence

+0

@Confluence la propiedad no es inaccesible desde dentro de la clase. – TZHX

+0

@TZHX Inaccesible puede significar que no es visible O no declarado. Todas las propiedades son inaccesibles por definición ya que no tengo propiedades declaradas. – Confluence

Cuestiones relacionadas