php - 从匿名回调访问外部类

时间:2015-03-31 16:08:24

标签: php class callback anonymous-function

我有这样的代码:

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方式,以便我可以在需要时停止服务器,而不是"过了一会儿"。

我需要这个,因为onConsume连接到流API并在新数据可用时运行匿名回调,并且由于某些锁定问题,我不想在超时时杀死php应用。我想优雅地停止服务器。

有人可以告诉我如何访问回调中的stopperstopServer吗?我可以使用以下语法吗?

...(function($data) use ($this) {...

我还想过将类值存储在回调中,但动态调用setStopper并且值可能不会更新!

有没有更好的方法来处理这种情况?

跟进: php - Dynamically update Singleton class' value

2 个答案:

答案 0 :(得分:1)

您可以围绕$consumer对象以及词汇对象$this创建Closure(如果您使用的是PHP< 5.4,则需要重命名$this其他东西,因为你不能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。

我还应该注意这里的完整性,如果这是一个长期存在的过程,那么在闭包内部引用的对象将在函数退出后很久就会挂起。例如:

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的额外引用将会一直存在,直到类实例本身被销毁。

没有意识到这可能导致一些严重的性能问题。

答案 1 :(得分:0)

同样的问题在这里我使用来自ob_start / ob_end_flush的输出缓冲区 我所拥有的一个函数应该是动态的(但是我推入的参数应该将它们插入一个数组中,以便以后用于使用 $ buffer 解析缓冲区) 在一次与ob_start关联的解析器中,我从一个充满数据的数组中得到这些代码行:

if(!empty($this->__b2))
        array_filter ($this->__b2,function($var)use(**&$buffer**){
                $buffer = preg_replace("/<\/body>/i", $var.'</body>', $buffer);
        });

我只使用一个班级单身,我使用&#34; ::&#34;很多。 你怎么看我的情况   array_filter在没有&amp; $ buffer

的情况下出现故障