2010-09-15 15 views
11

Estoy tratando de hacer referencia a una variable privada de un objeto desde dentro de un cierre. El código siguiente parece funcionar, pero se queja Fatal error: Cannot access self:: when no class scope is active in test.php on line 12 y Fatal error: Using $this when not in object context in test.php on line 20.Acceso a variables privadas desde dentro de un cierre

Alguna idea de cómo lograr los mismos resultados utilizando un cierre mientras se mantienen las variables privadas y sin hacer funciones de ayuda (lo que frustra la idea de una variable privada).

class MyClass 
{ 

    static private $_var1; 
    private $_var2; 

    static function setVar1($value) 
    { 
     $closure = function() use ($value) { 
      self::$_var1 = $value; 
     }; 
     $closure(); 
    } 

    function setVar2($value) 
    { 
     $closure = function() use ($value) { 
      $this->_var2 = $value; 
     }; 
     $closure(); 
    } 

} 

MyClass::setVar1("hello"); //doesn't work 

$myclass = new MyClass; 
$myclass->setVar2("hello"); //doesn't work 

Respuesta

14

Editar a tener en cuenta, esta respuesta estaba destinado originalmente para PHP5.3 y anteriores, es posible ahora. Para información actual, vea this answer.


Esto no es directamente posible. En particular, los cierres no tienen un alcance asociado, por lo que no pueden acceder a miembros privados y protegidos.

Puede, sin embargo, utilizar referencias:

<?php 
class MyClass 
{ 

    static private $_var1; 
    private $_var2; 

    static function setVar1($value) 
    { 
     $field =& self::$_var1; 
     $closure = function() use ($value, &$field) { 
      $field = $value; 
     }; 
     $closure(); 
    } 

    function setVar2($value) 
    { 
     $field =& $this->_var2; 
     $closure = function() use ($value, &$field) { 
      $field = $value; 
     }; 
     $closure(); 
    } 

} 

MyClass::setVar1("hello"); 

$myclass = new MyClass; 
$myclass->setVar2("hello"); 
+0

Je - imitador ;-) – DMI

+0

@Dave realidad estaba escribiendo antes de leer su respuesta. De todos modos, +1 para usted como solución: p – Artefacto

+0

Heh. Desarrollo paralelo rápido. ¡Gracias por el +1, y devuelto en especie mientras pones mucho más esfuerzo que yo! :-) – DMI

2

Los cierres tienen ningún concepto de $this o self - que no están vinculados a los objetos de esa manera. Esto significa que usted tendría que pasar a través de las variables de la cláusula use ... algo así como:

$_var1 =& self::$_var1; 
$closure = function() use ($value, &$_var1) { 
    $_var1 = $value; 
}; 

$_var2 =& $this->_var2; 
$closure = function() use ($value, &$_var2) { 
    $_var2 = $value; 
}; 

No he probado el código anterior, pero creo que es correcta.

+0

Eso no es correcto, al menos no en 5.4. Ver: http://php.net/manual/en/closure.bindto.php – GuyPaddock

4

Esto es posible a partir de PHP 5.4.0

class test { 
    function testMe() { 
     $test = new test; 
     $func = function() use ($test) { 
      $test->findMe();  // Can see protected method 
      $test::findMeStatically(); // Can see static protected method 
     }; 
     $func(); 
     return $func; 
    } 

    protected function findMe() { 
     echo " [find Me] \n"; 
    } 

    protected static function findMeStatically() { 
     echo " [find Me Statically] \n"; 
    } 
} 

$test = new test; 
$func = $test->testMe(); 
$func();  // Can call from another context as long as 
      // the closure was created in the proper context. 
+1

Solo para aclarar, ¿eso funcionaría también para 'private function findMe()'? –

Cuestiones relacionadas