Domanda

E 'possibile simulare le chiusure in PHP 5.2.x che non utilizzano globali? Potrei pensare ad un modo che sarebbe passato le variabili desiderate come parametri aggiuntivi per la chiusura, ma che proprio non si sente come le migliori pratiche.

Tutte le idee?

È stato utile?

Soluzione

Domanda interessante. Direi che non è possibile a tutti , ma vediamo

IBM - Cosa c'è di nuovo in PHP5. 3, parte 2

  

La chiusura è una funzione che viene valutata nel suo ambiente, che ha una o più variabili legate che può essere letta quando viene chiamata la funzione.

e l'ulteriore (sottolineatura mia)

  

Le variabili da importare dall'ambiente esterno sono specificati nella clausola uso della definizione della funzione di chiusura. Per impostazione predefinita, sono passati per valore , il che significa che se vogliamo aggiornare il valore passato nella definizione di funzione di chiusura, non sarebbe aggiornare il valore esterno.

Uso global passerebbe per riferimento e sebbene sia possibile associare variabili di riferimento con una chiusura utilizzando & nella clausola use, è già una deviazione dal comportamento 5.3 predefinito.

$var = 'yes';
$fn  = create_function('', 'global $var; $var = "no";');
$fn();
echo $var; // outputs no

Si potrebbe copiare la variabile globale al fine di utilizzarlo per valore, però, per es.

$var = 'yes';
$fn  = create_function('', 'global $var; $tmp = $var; $tmp = "no";');
$fn();
echo $var; // outputs yes

Inoltre, non sarà valutato il valore della variabile globale (quando si utilizza create_function) (bound) quando la funzione si crea ma quando si esegue la funzione

$var = 'yes';
$fn  = create_function('', 'global $var; $tmp = $var; return $tmp;');
$var = 'maybe';
echo $fn(); // outputs maybe

$var = 'yes';
$fn  = function() use ($var) { return $var; };
$var = 'maybe';
echo $fn(); // outputs yes

Importante è anche

  

Quando definito all'interno di un oggetto, una cosa a portata di mano è che la chiusura ha pieno accesso all'oggetto tramite la variabile $ this, senza la necessità di importare in modo esplicito. * Anche se penso che questo è stato abbandonato nel PHP5.3 finale

Questo è impossibile con la parola chiave global e anche voi non si può semplicemente utilizzare $this. Non c'è modo per fare riferimento a una proprietà da una classe quando si definisce il corpo della funzione con create_function.

class A {

    protected $prop = 'it works';

    public function test()
    {
        $fn = create_function('', 'echo $this->prop;');
        return $fn;
    }
}

$a = new A;
$fn = $a->test();
$fn();

si tradurrà in

Fatal error: Using $this when not in object context

Per riassumere questo
Mentre è possibile creare una funzione di importazione di una variabile dal campo di applicazione globale, è possibile non si può non creare uno utilizzando le variabili da un altro ambito. E perché si sono tecnicamente non impegnativo quando si utilizza create_function ma l'importazione quando viene eseguita la funzione creata, mi piacerebbe discutere questa limitazione rende la chiusura di una lambda .


EDIT: La soluzione offerta da Onno Marsman sotto è abbastanza decente però. E non simula completamente chiusure, ma l'implementazione è abbastanza vicino.

Altri suggerimenti

La mia soluzione: http : //techblog.triptic.nl/simulating-closures-in-php-versions-prior-to-php-5-3/

Essa tuttavia passa le variabili all'interno di un oggetto alla chiusura come primo argomento.

Ci sono alcuni casi particolari in cui è possibile farlo.

Se avete bisogno di catturare una variabile per valore (non per riferimento), e il valore è un semplice tipo di valore come un numero, una stringa, o un array di quanto sopra (non fare riferimento tipi come gli oggetti e le risorse e funzioni), quindi si può semplicemente inserirlo nella definizione della funzione utilizzando var_export():

$var = array(1, 3);
$f = create_function('',
    '$var=' . var_export($var,true) . '; return $var;');

Se avete bisogno di catturare la variabile di riferimento al fine di mantenere lo stato mutevole tra le chiamate della funzione, ma non è necessario avere le modifiche riflesse nel perimetro originale in cui è stato creato (ad esempio, per creare un accumulatore, ma le modifiche alla somma non hanno bisogno di modificare la variabile somma del perimetro creazione), allora si può allo stesso modo inserirla, ma come una variabile statica:

function make_accumulator($sum) {
    $f = create_function('$x',
        'static $var=' . var_export($var,true) . '; return $var += $x;');
    return $f;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top