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

php - Access outer class from an anonymous callback

我有这样的代码:

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 方式,这样我就可以在需要时停止服务器,而不是 "after a while".

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

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

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

我也想过在回调中存储class值,但是setStopper是动态调用的,值可能不会更新!

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

跟进:

您可以围绕 $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

这是闭包的 classic 示例。通常,一旦 makeAdder 函数 returns 其内部变量 $x 将超出范围并准备好进行垃圾收集。然而,由于它被绑定在匿名函数的范围内,它将无限期地挂起(直到脚本终止)对包含范围的引用也被释放(即通过unset($adder) ).这意味着一旦您的函数被调用,对 $consumer$this$stopper 的额外引用将一直存在,直到 class 实例本身被销毁。

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

同样的问题,我使用来自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);
        });

我只使用一个 class 单例,而且我经常使用“::”。 你怎么看我的情况 array_filter 在没有 &$buffer

的情况下是乱序的