使用匿名函数作为参数访问外部变量


93

基本上,我使用此方便的函数来处理数据库行(请注意PDO和/或其他内容)

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

使用此功能,我可以简单地执行以下操作:

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

假设现在我需要将所有内容都串联$r['title']在var中(这只是一个示例)。

我该怎么办?我当时在想这样的事情,但它不是很优雅:

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

echo $result;

Answers:


188

你必须使用use在文档中所述

闭包也可以从父范围继承变量。任何此类变量必须在函数头中声明。从父作用域继承变量与使用全局变量不同。全局变量存在于全局范围内,无论执行什么功能,该变量都是相同的。

码:

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

但是要当心(摘自上一链接的评论之一):

use()参数是早期绑定-它们在声明lambda函数的位置而不是在调用lambda函数的位置(后期绑定)使用变量的值。


1
不应该消除全球减速吗?
aziz punjani 2011年

19
+1强调early binding。但是我想在上面的示例中,use (&$result)通过引用传递时真的没有关系吗?
Dimitry K

4
@DimitryK是的,这里使用引用来绕过默认行为(早期绑定)。
Xaerxess 2014年

3
@machineaddict最基本的use 早期绑定-如果您指的是后期绑定的解决方法-您将通过use引用传递变量-使用&=> use (&$result)$result在调用匿名函数(或调用它的东西)之前使用alter variable
jave.web

1
由于类实例始终通过引用传递,因此您无需为它们使用&。(除非您完全覆盖实例)。
乔尔·哈克斯

0

重写'fetch'只调用$ func一次呢?

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

这样,您将只调用一次$ func并在获取后重新处理该数组?即使对函数调用200次也不是很确定的效果。


是的,你是对的。但是,如果您有兴趣在这里和那里获取几毫秒的信息,可以使用mysql_fetch_row()而不是mysql_fetch_assoc()……由于您必须知道列的位置,因此很难处理。这样,您就可以将2000个请求(每个30行)从0.205传递到0.180。
user103307 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.