2011-12-05 1 views
80

Il PHP manuale indica

Non è possibile utilizzare $this dalla funzione anonima prima di PHP 5.4.0

su anonymous functions page. Ma ho scoperto che posso farlo funzionare assegnando $this a una variabile e passando la variabile a un'istruzione use alla definizione della funzione.

$CI = $this; 
$callback = function() use ($CI) { 
    $CI->public_method(); 
}; 

È una buona pratica?
C'è un modo migliore per accedere a $this all'interno di una funzione anonima usando PHP 5.3?

+1

solo una convenzione minore forum - di solito è meglio accettare una risposta che per modificare una domanda in modo da riflettere la risposta preferita. Principalmente questo è così che le risposte hanno ancora senso in perpetuo, ma ovviamente anche per dare credito per una risposta corretta. – halfer

+3

Attenzione che '$ CI = $ this;' e '$ CI = & $ this;' ** non sono ** in realtà identici. Forse per i tuoi scopi, ma non sono la stessa cosa. Prova '$ CI = 'bla'; var_dump ($ this); 'con entrambe le versioni per vedere la differenza. – Rudie

+1

@Rudie Sto aggiungendo la [documentazione] (http://php.net/manual/en/language.oop5.references.php) per il tuo commento – steampowered

risposta

61

Non riuscirà quando si tenta di chiamare un metodo protetto o privato su di esso, perché utilizzarlo in quel modo conta come chiamare dall'esterno. Non v'è alcun modo per aggirare il punto 5.3 per quanto ne so, ma venire PHP 5.4, funzionerà come previsto, fuori dalla scatola:

class Hello { 

    private $message = "Hello world\n"; 

    public function createClosure() { 
     return function() { 
      echo $this->message; 
     }; 
    } 

} 
$hello = new Hello(); 
$helloPrinter = $hello->createClosure(); 
$helloPrinter(); // outputs "Hello world" 

Ancor più, si sarà in grado di cambiare ciò che $ ciò mette in evidenza in fase di esecuzione, per le funzioni via anonima (chiusura rebinding):

class Hello { 

    private $message = "Hello world\n"; 

    public function createClosure() { 
     return function() { 
      echo $this->message; 
     }; 
    } 

} 

class Bye { 

    private $message = "Bye world\n"; 

} 

$hello = new Hello(); 
$helloPrinter = $hello->createClosure(); 

$bye = new Bye(); 
$byePrinter = $helloPrinter->bindTo($bye, $bye); 
$byePrinter(); // outputs "Bye world" 

in effetti, le funzioni via anonima avranno un bindTo() method, dove il primo parametro può essere utilizzato per specificare quali $ this punti, e la seconda controlli dei parametri quale dovrebbe essere il livello di visibilità. Se ometti il ​​secondo parametro, la visibilità sarà come chiamare dal "fuori", ad es. è possibile accedere solo a proprietà pubbliche. Prendi nota di come funziona bindTo, non modifica la funzione originale, ne restituisce uno nuovo.

+1

Contrassegnare la risposta corretta, ma solo per chiarire per altri lettori: la convenzione usato nella domanda funzionerà con metodi pubblici usando l'oggetto che fa riferimento a '$ this'. – steampowered

+5

[metodi non pubblici] (http://stackoverflow.com/a/6386863/90527) è possibile accedere utilizzando la riflessione. Inefficiente e un po 'cattivo, ma funziona. – outis

1

Questo sembra giusto se passate per riferimento è il modo corretto per farlo. Se usi PHP 5 non hai bisogno del simbolo & prima del $this perché passerà sempre per riferimento indipendentemente.

+2

L'OP deve utilizzare 5.3 o versioni successive, poiché 4.x non supportava funzioni anonime :-) – halfer

1

Questo va bene. Io penso che si possa fare anche questo:

$CI = $this; 

... dal assegnazioni che coinvolgono oggetti saranno sempre copiare i riferimenti, non oggetti interi.

5

Questo è il modo normale in cui è stato eseguito.
b.t.w, prova a rimuovere il & dovrebbe funzionare senza questo, come gli oggetti passano con ref in qualsiasi modo.

5

Non sempre fare affidamento su PHP per passare gli oggetti per riferimento, quando si assegna un riferimento in sé, il comportamento non è lo stesso della maggior parte delle lingue OO in cui viene modificato il puntatore originale.

tuo esempio:

$CI = $this; 
$callback = function() use ($CI) { 
$CI->public_method(); 
}; 

dovrebbe essere:

$CI = $this; 
$callback = function() use (&$CI) { 
$CI->public_method(); 
}; 

NOTA DI RIFERIMENTO "&" e $ CI dovrebbero essere assegnati dopo le chiamate finali su di esso è stato fatto, ancora una volta altrimenti si potrebbe avere output imprevedibile, in PHP l'accesso a un riferimento non è sempre lo stesso dell'accesso alla classe originale, se questo ha senso.

http://php.net/manual/en/language.references.pass.php