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. So far I have set_time_limit
to stop the code after a while. But I need to implement setStopper
way so I can stop the server whenever needed, not "after a while".
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. I want to gracefully stop the server.
Can anyone please tell how to access the stopper
or stopServer
inside the callback? 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!
Is there a better way to handle this situation?
Follow Up: php - Dynamically update Singleton class' value
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)
):
$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.
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. 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 (i.e. via 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.
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 :
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