Usare "$ this" in una funzione anonima in PHP pre 5.4.0


86

Il manuale PHP afferma

Non è possibile utilizzare $thisdalla funzione anonima prima di PHP 5.4.0

nella pagina delle funzioni anonime . Ma ho scoperto che posso farlo funzionare assegnando $thisa una variabile e passando la variabile a useun'istruzione nella definizione della funzione.

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

È una buona pratica?
C'è un modo migliore per accedere $thisall'interno di una funzione anonima utilizzando PHP 5.3?


1
Solo una convenzione minore del forum: di solito è meglio accettare una risposta che modificare una domanda per riflettere la tua risposta preferita. Principalmente è così che le risposte hanno ancora un senso per sempre, ma ovviamente anche per dare credito a una risposta corretta.
halfer

4
Attenzione a questo $CI = $this;e $CI =& $this; non sono effettivamente 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 per il tuo commento
potenziato il

@steampowered C'è un buon esempio / articolo online da qualche parte su questo, ma non sono riuscito a trovarlo =) Scusa. Provalo se non vedi la differenza. Allora è ovvio.
Rudie

Risposte:


67

Fallirà quando proverai a chiamare un metodo protetto o privato su di esso, perché utilizzarlo in questo modo conta come chiamare dall'esterno. Non c'è modo di aggirare questo in 5.3 per quanto ne so, ma come PHP 5.4, funzionerà come previsto, fuori dagli schemi:

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"

Inoltre, sarai in grado di modificare ciò a cui $ this punta in fase di esecuzione, per le funzioni anonymus (rebinding di chiusura):

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 anonymus avranno un metodo bindTo () , in cui il primo parametro può essere utilizzato per specificare a cosa punta $ this, e il secondo parametro controlla quale dovrebbe essere il livello di visibilità . Se ometti il ​​secondo parametro, la visibilità sarà come una chiamata da "fuori", es. è possibile accedere solo alle proprietà pubbliche. Prendi nota anche del modo in cui funziona bindTo, non modifica la funzione originale, ne restituisce una nuova .


1
Contrassegnare la risposta corretta, ma solo per chiarire agli altri lettori: la convenzione utilizzata nella domanda funzionerà per i metodi pubblici che utilizzano l'oggetto che fa riferimento $this.
Steampowered

5
È possibile accedere a metodi non pubblici utilizzando la riflessione. Inefficiente e un po 'malvagio, ma funziona.
uscita

7

Non fare sempre affidamento su PHP per passare oggetti per riferimento, quando assegni un riferimento stesso, il comportamento non è lo stesso della maggior parte dei linguaggi OO in cui viene modificato il puntatore originale.

il tuo esempio:

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

dovrebbe essere:

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

NOTA IL RIFERIMENTO "&" e $ CI dovrebbero essere assegnati dopo che le chiamate finali su di esso sono state fatte, di nuovo altrimenti potresti avere un output imprevedibile, in PHP accedere a un riferimento non è sempre lo stesso che accedere alla classe originale - se ha senso.

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


6

Questo è il modo normale in cui è stato fatto.
btw, prova a rimuovere &dovrebbe funzionare senza questo, poiché gli oggetti passano per ref in qualsiasi modo.


1

Sembra a posto se il tuo passaggio per riferimento è il modo corretto di farlo. Se stai usando PHP 5 non hai bisogno del &simbolo prima $thisin quanto passerà sempre per riferimento a prescindere.


2
L'OP deve usare 5.3 o superiore, poiché 4.x non supportava le funzioni anonime :-)
halfer

1

Questo va bene. Dovrei pensare che potresti fare anche questo:

$CI = $this;

... poiché le assegnazioni che coinvolgono oggetti copieranno sempre i riferimenti, non interi oggetti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.