Accesso alla variabile esterna utilizzando la funzione anonima come parametri


93

Fondamentalmente uso questa comoda funzione per elaborare le righe del db (chiudi un occhio su PDO e / o altre cose)

function fetch($query,$func) {
    $query = mysql_query($query);   
    while($r = mysql_fetch_assoc($query)) {
        $func($r);
    }
}

Con questa funzione posso semplicemente fare:

fetch("SELECT title FROM tbl", function($r){
   //> $r['title'] contains the title
});

Diciamo ora che devo concatenare tutto $r['title']in una var (questo è solo un esempio).

Come potrei farlo? Stavo pensando qualcosa del genere, ma non è molto elegante:

$result = '';
fetch("SELECT title FROM tbl", function($r){
   global $result;
   $result .= $r['title'];
});

echo $result;

Risposte:


188

Devi usare usecome descritto nei documenti :

Le chiusure possono anche ereditare variabili dall'ambito padre. Qualsiasi variabile di questo tipo deve essere dichiarata nell'intestazione della funzione. Ereditare variabili dall'ambito padre non è la stessa cosa che utilizzare variabili globali. Le variabili globali esistono nell'ambito globale, che è lo stesso indipendentemente dalla funzione in esecuzione.

Codice:

$result = '';
fetch("SELECT title FROM tbl", function($r) use (&$result) {
   $result .= $r['title'];
});

Ma attenzione (tratto da uno dei commenti nel link precedente):

I parametri use () sono associazione anticipata: usano il valore della variabile nel punto in cui viene dichiarata la funzione lambda, piuttosto che nel punto in cui viene chiamata la funzione lambda (associazione tardiva).


1
Quella decelerazione globale non dovrebbe essere rimossa?
aziz punjani

19
+1 per sottolineare il early binding. Tuttavia immagino che nell'esempio sopra quando use (&$result)viene passato per riferimento non sia davvero importante?
Dimitry K

4
@DimitryK Sì, il riferimento viene utilizzato qui per ignorare il comportamento predefinito (associazione anticipata).
Xaerxess

3
@machineaddict La base use è l' associazione anticipata - se intendi una soluzione alternativa per l'associazione tardiva - dovresti passare la variabile per useriferimento - usando &=> use (&$result)e alterare la $resultvariabile prima di chiamare la funzione anonima (o qualcosa del genere, che la chiama)
jave.web

1
Poiché le istanze di classe vengono sempre passate per riferimento, non sarà necessario utilizzare & per esse. (a meno che tu non sovrascrivi completamente l'istanza).
Joel Harkes

0

Che ne dici di riscrivere 'fetch' per chiamare $ func solo una volta?

function fetch($query,$func) {
    $query = mysql_query($query);   
    $retVal = array();
    while($r = mysql_fetch_assoc($query)) {
        $retVal[] = $r;
    }
    $func($retVal);
}

In questo modo chiameresti $ func solo una volta e rielaborerai l'array una volta recuperato? Non sono sicuro delle prestazioni anche se chiamare 200 volte una funzione non sembra una buona idea.


Si hai ragione. Tuttavia, potresti usare mysql_fetch_row () invece di mysql_fetch_assoc () se sei interessato a guadagnare qualche ms qua e là ... è semplicemente terribilmente difficile da gestire perché dovresti conoscere la posizione delle tue colonne. In questo modo si passa da 0,205 a 0,180 su 2000 richieste di 30 righe ciascuna.
user103307
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.