Accediendo a la variable externa usando una función anónima como parámetros

93

Básicamente, utilizo esta práctica función para procesar filas de base de datos (cierre un ojo en PDO y / u otras cosas)

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

Con esta función simplemente puedo hacer:

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

Digamos que ahora necesito concatenar todo $r['title']en una var (esto es solo un ejemplo).

¿Cómo puedo hacer eso? Estaba pensando en algo como esto, pero no es muy elegante:

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

echo $result;
dinámica
fuente

Respuestas:

188

Tienes que usarlo usecomo se describe en los documentos :

Los cierres también pueden heredar variables del ámbito principal. Cualquiera de estas variables debe declararse en el encabezado de la función. Heredar variables del ámbito principal no es lo mismo que usar variables globales. Las variables globales existen en el ámbito global, que es el mismo sin importar qué función se esté ejecutando.

Código:

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

Pero cuidado (tomado de uno de los comentarios en el enlace anterior):

Los parámetros use () son de enlace temprano: usan el valor de la variable en el punto donde se declara la función lambda, en lugar del punto donde se llama a la función lambda (enlace tardío).

Xaerxess
fuente
1
¿No debería eliminarse esa desaceleración global?
aziz punjani
19
+1 para enfatizar el early binding. Sin embargo, supongo que en el ejemplo anterior, cuando use (&$result)se pasa por referencia, ¿realmente no importa?
Dimitry K
4
@DimitryK Sí, la referencia se usa aquí para omitir el comportamiento predeterminado (enlace temprano).
Xaerxess
3
@machineaddict Lo básico use es el enlace temprano - si te refieres a una solución para el enlace tardío - pasarías la variable usepor referencia - usando &=> use (&$result)y alterar la $resultvariable antes de llamar a la función anónima (o algo que la llame)
jave.web
1
Dado que las instancias de clase siempre se pasan por referencia, no necesitará usar & para ellas. (a menos que sobrescriba completamente la instancia).
Joel Harkes
0

¿Qué hay de reescribir 'fetch' para llamar a $ func solo una vez?

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

De esta manera, ¿llamaría a $ func solo una vez y volvería a procesar la matriz una vez recuperada? No estoy seguro del rendimiento, incluso aunque llamar 200 veces una función no parece una buena idea.

user103307
fuente
Sí, tiene usted razón. Sin embargo, puede usar mysql_fetch_row () en lugar de mysql_fetch_assoc () si está interesado en ganar algunos ms aquí y allá ... es tremendamente difícil de manejar, ya que tendría que conocer la posición de sus columnas. Al hacerlo, pasa de 0,205 a 0,180 en 2000 solicitudes de 30 filas cada una.
user103307