2010-09-15 3 views
11

Sto provando a fare riferimento a una variabile privata di un oggetto all'interno di una chiusura. Il codice sotto sembra funzionare, ma si lamenta Fatal error: Cannot access self:: when no class scope is active in test.php on line 12 e Fatal error: Using $this when not in object context in test.php on line 20.Accesso a variabili private da una chiusura

Qualsiasi idea su come ottenere gli stessi risultati utilizzando una chiusura mantenendo le variabili private e senza fare funzioni di supporto (annullando l'intera idea di una variabile privata).

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 

risposta

14

Modifica da notare, questa risposta è stato originariamente pensato per PHP5.3 e versioni precedenti, è possibile ora. Per informazioni aggiornate, vedere this answer.


Questo non è direttamente possibile. In particolare, le chiusure non hanno un ambito associato, quindi non possono accedere ai membri privati ​​e protetti.

È possibile, tuttavia, utilizzare i riferimenti:

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

Eh - copycat ;-) – DMI

+0

@ Dave in realtà stavo scrivendo prima ho letto la tua risposta. Ad ogni modo, +1 per te come soluzione: p – Artefacto

+0

Heh. Rapido sviluppo parallelo. Grazie per il +1, e restituito in natura, come si mette molto più impegno in me! :-) – DMI

2

chiusure non hanno il concetto di $this o self - non sono legati agli oggetti in quel modo. Questo significa che si dovrà passare le variabili attraverso la clausola use ... qualcosa di simile:

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

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

Non ho ancora testato il codice di cui sopra, ma credo che sia corretto.

+0

Questo non è corretto, almeno non in 5.4. Vedi: http://php.net/manual/en/closure.bindto.php – GuyPaddock

4

Questo è possibile a partire dal 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

Giusto per chiarire, funzionerebbe anche per 'funzione privata findMe()'? –