问题描述
我有这样的代码:
class Server {
private $stopper;
public function setStopper() { $this->stopper = TRUE; }
public function startServer() {
$consumer = new Consumer();
$consumer->onConsume(function($data) {
global $consumer;
// some processing
if( ?? ) { // how to access stopper here??
$consumer->stop();
// also how to access stopServer() here??
}
});
$consumer->consume();
}
public function stopServer() { ... }
}
此代码位于一个文件中,除非调用 setStopper()
,否则它将永远运行.到目前为止,我有 set_time_limit
可以在一段时间后停止代码.但是我需要实现 setStopper
方式,这样我就可以在需要时停止服务器,而不是一段时间后".
This code is in a file that should run forever unless the setStopper()
is called. So far I have set_time_limit
to stop the code after a while. But I need to implement setStopper
way so I can stop the server whenever needed, not "after a while".
我需要这个,因为 onConsume
已连接到流 API 并在新数据可用时运行匿名回调,并且我不想因某些锁定而在超时时终止 php 应用程序问题.我想优雅地停止服务器.
I need this because, the onConsume
is connected to a streaming API and runs the anonymous call back whenever new data is available and I don't want kill the php app on timeout due to some lock issues. I want to gracefully stop the server.
谁能告诉我如何访问回调中的 stopper
或 stopServer
?我可以使用以下语法吗?
Can anyone please tell how to access the stopper
or stopServer
inside the callback? Can I use following syntax?
...(function($data) use ($this) {...
我也想过将类值存储在回调中,但是setStopper
是动态调用的,值可能不会更新!
I also thought of storing the class value inside callback, but the setStopper
is called dynamically and the value might not be updated!
有没有更好的方法来处理这种情况?
Is there a better way to handle this situation?
跟进: php - 动态更新单例类的值
推荐答案
您可以创建一个$consumer
对象以及词法对象 $this
周围的闭包(如果您使用的是 PHP $this 到别的东西,因为你不能use($this)
):
You can create a Closure around the $consumer
object as well as the lexical object $this
(if you're using PHP < 5.4, you need to rename $this
to something else, because you cannot use($this)
):
$self = $this;
// You may not need to do this, I cannot remember off-hand whether
// closures have access to private variables or not
$stopper = $this->stopper;
$consumer->onConsume(function($data) use($consumer, $self, $stopper) {
if( $stopper ) {
$consumer->stop();
$self->stopServer();
}
});
参见手册页链接上的示例 #3.
See Example #3 on the linked to manual page.
为了完整起见,我还应该在这里注意,如果这是一个长期存在的过程,那么在闭包内引用的对象将在函数退出后长时间挂起.例如:
I should also note here for completeness that if this is a long-lived process, then the objects being referenced inside the closure will hang around long after the function exits. For instance:
function makeAdder($x) {
return function($n) use($x) {
return $x + $n;
};
}
$adder = makeAdder(5);
echo $adder(2); // Output 7
echo $adder(5); // Output 10
echo $adder(4); // Output 9
这是一个闭包的经典例子.通常,一旦 makeAdder
函数返回其内部变量 $x
将超出范围并准备好进行垃圾收集.然而,由于它绑定在匿名函数的作用域内,它将无限期地挂起(直到脚本终止)或对包含作用域的引用也被释放(即通过 unset($adder)
).这意味着一旦您的函数被调用,对 $consumer
、$this
和 $stopper
的额外引用将一直存在,直到类实例本身摧毁了.
This is a classic example of a closure. Normally, once the makeAdder
function returns its inner variable $x
will fall out of scope and be ready for garbage collection. Since it is however bound inside the anonymous function's scope, it will hang around indefinitely (until the script's termination) or the reference to the containing scope is also released (i.e. via unset($adder)
). This means that once your function is called, extra references to $consumer
, $this
and $stopper
will hang around until the class instance itself is destroyed.
不了解这一点可能会导致一些严重的性能问题.
Not being aware of this can lead to some serious performance issues.
这篇关于php - 从匿名回调访问外部类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!