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;

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).


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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.