2010-09-15 8 views
11

J'essaie de référencer une variable privée d'un objet à l'intérieur d'une fermeture. Le code ci-dessous semble fonctionner, mais il se plaint Fatal error: Cannot access self:: when no class scope is active in test.php on line 12 et Fatal error: Using $this when not in object context in test.php on line 20. Des idées pour obtenir les mêmes résultats en utilisant une fermeture tout en gardant les variables privées et sans faire de fonctions auxiliaires (en éliminant toute l'idée d'une variable privée).Accès à des variables privées à partir d'une fermeture

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 

Répondre

14

Modifier à noter, cette réponse était à l'origine destiné à PHP5.3 et plus tôt, il est possible maintenant. Pour plus d'informations, voir this answer.


Ceci n'est pas directement possible. En particulier, les fermetures n'ont pas de portée associée, de sorte qu'elles ne peuvent pas accéder aux membres privés et protégés.

Vous pouvez cependant utiliser des références:

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

Heh - imitateur ;-) – DMI

+0

j'écrivais @ Dave réellement avant d'avoir lu votre réponse. De toute façon, +1 pour vous en tant que règlement: p – Artefacto

+0

Heh. Développement parallèle rapide. Merci pour le +1, et revenu en nature alors que vous mettez beaucoup plus d'efforts que moi! :-) – DMI

2

Les bouclages ont aucune notion de $this ou self - ils ne sont pas liés à des objets de cette façon. Cela signifie que vous devez passer les variables par la clause use ... quelque chose comme:

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

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

Je ne l'ai pas testé le code ci-dessus, mais je crois qu'il est correct.

+0

Ce n'est pas correct, au moins pas dans 5.4. Voir: http://php.net/manual/en/closure.bindto.php – GuyPaddock

4

Ceci est possible à 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

Juste pour clarifier, cela fonctionnerait-il aussi pour 'private function findMe()'? –

Questions connexes