简体   繁体   English

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

[英]php - Access outer class from an anonymous callback

I have a code like this: 我有这样的代码:

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() { ... }

}

This code is in a file that should run forever unless the setStopper() is called. 除非调用setStopper()否则此代码位于应永久运行的文件中。 So far I have set_time_limit to stop the code after a while. 到目前为止,我已经使用set_time_limit在一段时间后停止了代码。 But I need to implement setStopper way so I can stop the server whenever needed, not "after a while". 但是我需要实现setStopper方式,以便可以在需要时停止服务器,而不是“过一会儿”。

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. 我需onConsume ,因为onConsume连接到流API并在有新数据可用时运行匿名回调,并且由于某些锁定问题,我不想在超时时onConsume php应用。 I want to gracefully stop the server. 我想优雅地停止服务器。

Can anyone please tell how to access the stopper or stopServer inside the callback? 谁能告诉我如何在回调中访问stopperstopServer Can I use following syntax? 我可以使用以下语法吗?

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

I also thought of storing the class value inside callback, but the setStopper is called dynamically and the value might not be updated! 我还考虑过将类值存储在回调中,但是setStopper是动态调用的,该值可能不会更新!

Is there a better way to handle this situation? 有没有更好的方法来处理这种情况?

Follow Up: php - Dynamically update Singleton class' value 跟进: php-动态更新Singleton类的值

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) ): 您可以在$consumer对象以及词法对象$this周围创建一个Closure (如果您使用的是PHP <5.4,则需要将$this重命名$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();
  }
});

See Example #3 on the linked to manual page. 请参阅链接到手册页上的示例3。

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

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. 通常,一旦makeAdder函数返回其内部变量$x它将超出范围并准备进行垃圾回收。 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 (ie via unset($adder) ). 但是,由于它绑定在匿名函数的作用域内,因此它将无限期地挂起(直到脚本终止), 或者也释放了对包含作用域的引用(即,通过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. 这意味着一旦调用了函数,对$consumer$this$stopper额外引用将一直存在,直到类实例本身被销毁为止。

Not being aware of this can lead to some serious performance issues. 不了解这一点可能会导致一些严重的性能问题。

the same problem here i use output buffers from ob_start/ob_end_flush and one function i have should be dynamic (however parameters i push into should insert them in an array for later use for parsing buffers using $buffer ) in the parser associated to ob_start at a time i have these lines of code from one array full of data : 相同的问题在这里,我使用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);
        });

I use a only one class singleton ,and i use "::" a lot. 我只使用一个类的单例,并且经常使用“ ::”。 How you see in my case array_filter was out of order without &$buffer 在我的情况下,您如何看待没有&$ buffer的array_filter出现故障

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM