php – доступ к внешнему классу с анонимного обратного вызова

У меня такой код:

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 при тайм-ауте из-за некоторых проблем с блокировкой. Я хочу изящно остановить сервер.

Может ли кто-нибудь рассказать, как получить доступ к stopServer или stopServer внутри обратного вызова? Могу ли я использовать следующий синтаксис?

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

Я также думал о сохранении значения класса внутри обратного вызова, но setStopper называется динамически, и значение может не обновляться!

Есть ли лучший способ справиться с этой ситуацией?

Follow Up: php – динамическое обновление значения Singleton class

    Вы можете создать Closure вокруг объекта $consumer а также лексического объекта $this (если вы используете 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 функция makeAdder возвращает свою внутреннюю переменную $x она выпадет из области видимости и будет готова к сбору мусора. Поскольку он, однако, связан с областью анонимной функции, он будет бесконечно зависать (до завершения сценария) или ссылки на содержащую область видимости (т.е. через unset($adder) ). Это означает, что после вызова вашей функции дополнительные ссылки на $consumer , $this и $stopper будут зависать, пока сам экземпляр класса не будет уничтожен.

    Не осознавая этого, это может привести к серьезным проблемам с производительностью.

    та же проблема здесь я использую выходные буферы из ob_start / ob_end_flush, и одна функция i должна быть динамической (однако параметры, которые я вставляю, должны вставлять их в массив для последующего использования для разбора буферов с использованием $ buffer ) в парсере, связанном с ob_start при я имею эти строки кода из одного массива, полного данных:

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

    Я использую только один класс singleton, и я использую «::» много. Как вы видите, в моем случае array_filter вышел из строя без буфера & $