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

dyn*_*mic 89 php closures scope

基本上我使用这个方便的函数来处理数据库行(关注PDO和/或其他东西)

function fetch($query,$func) {
    $query = mysql_query($query);   
    while($r = mysql_fetch_assoc($query)) {
        $func($r);
    }
}
Run Code Online (Sandbox Code Playgroud)

有了这个功能,我可以简单地做到:

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

现在假设我需要$r['title']在var中连接所有内容(这只是一个例子).

我怎么能这样做?我在想这样的东西,但它不是很优雅:

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

echo $result;
Run Code Online (Sandbox Code Playgroud)

Xae*_*ess 178

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

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

码:

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

但要注意(取自上一个链接中的一条评论):

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

  • +1用于强调"早期绑定".但是我想在上面的例子中,当通过引用传递`use(&$ result)`时,它真的不重要吗? (16认同)
  • @DimitryK是的,这里使用引用来绕过默认行为(早期绑定). (4认同)
  • @machineaddict基本的`use`**是**早期绑定 - 如果你的意思是后期绑定的解决方法 - 你会通过引用传递变量`use` - 使用`&`=>`use(&$ result)`和在调用匿名函数之前改变`$ result`变量(或调用它的东西) (2认同)