2015-03-31 2 views
1

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

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

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

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

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

Follow Up:php - Dynamically update Singleton class' value

ответ

1

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

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

+0

делает обновление '' стопор в 'setStopper' влияют на' $ stopper' внутри обратного вызова? Все ли «по ссылке» в php? –

+0

Объекты есть, да. См. [Здесь] (http://stackoverflow.com/questions/2715026/are-php5-objects-passed-by-reference) –

+0

Хорошо, тогда! Я обновлю свой код и проверю, работает ли его, спасибо и дам вам знать –

0

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^