【发布时间】:2015-09-27 18:19:11
【问题描述】:
我的代码如下所示:
$app->add(function($req, $res, $next) {
# closure A
$res->on('end', function($res) use ($req) {
# closure B
});
$next();
});
如您所见,我在闭包中有一个闭包。闭包 B 正在接收来自事件的$response,所以它没有问题。但它也是来自闭包 A 的 useing $request。
在这里,我对use'd 变量的范围有疑问,我看到了两种可能性:
- 任何响应都会有自己的请求对象,因为闭包 B 会为每个传递给
$res->on的新侦听器重新创建。因此,有许多闭包 B 的作用域从闭包 A 的已用变量继承一次。 - 或者:任何新请求都将替换闭包 A 中的
$req和$res(正常行为...)但也将替换先前创建的闭包 B 使用的$req。如果在请求 #2 到达之前,请求 #1 未得到响应(这是基于事件循环的异步代码)。
我希望我已经足够清楚了。我问这个是因为,例如,在 JavaScript 中,我们有时必须使用回调生成器来确保子闭包的范围不会被替换。
编辑:我尝试了一个理论上做同样事情但更容易测试的代码:
$a = function($var) {
return function() use ($var) {
var_dump($var);
};
};
$fn1 = $a((object) ['val' => 1]);
$fn2 = $a((object) ['val' => 2]);
$fn2();
$fn1();
输出 (2, 1) 表明第一个函数 $fn1 保持其原始范围。另外,我注意到 var_dump 在 Closure 对象上的输出显示了它带来的范围:
object(Closure)#3 (1) {
["static"]=>
array(1) {
["res"]=>
object(stdClass)#2 (1) {
["val"]=>
int(1)
}
}
}
技术解释?我认为这是因为 PHP 中的闭包是常规的 PHP 对象,其中 use 是一种构造函数。
- 上面示例中的闭包行为如下:http://pastebin.com/qkQ5GDFw
- 但不是这样,我强制 PHP 保持相同的引用,这对于闭包的“构造函数”是不可能的:http://pastebin.com/ixfVh2Uf
我说的对吗?有 PHP 专家吗?
【问题讨论】: