18958

php - Access outer class from an anonymous callback

Question:

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?

<strong>Follow Up:</strong> <a href="https://stackoverflow.com/questions/29374529" rel="nofollow">php - Dynamically update Singleton class' value</a>

Answer1:

You can create a <a href="http://php.net/manual/en/functions.anonymous.php" rel="nofollow">Closure</a> 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) <em>or</em> 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.

Answer2:

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 <strong>$buffer</strong>) 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 <strong>array_filter was out of order without &$buffer</strong>

Recommend

  • Excel not inserting leading zero
  • pythonanywhere - How do I use websockets to transmit messages as per the web2py messaging example?
  • MVC - @Html.CheckBoxFor
  • ZipList with Scalaz
  • Alamofire and Reachability.swift not working on xCode8-beta5
  • How can I tell a form not to dispose a particular control when it closes?
  • Hash Code in SQL Server?
  • Defined variables not working in javascript files when I use getScript
  • Can't remove headers after they are sent
  • How to synchronize jQuery dialog box to act like alert() of Javascript
  • Question about instantiating object
  • Intel-64 and ia32 atomic operations acquire-release semantics and GCC 5+
  • List images(01.png) and descriptions(01.txt) from directory
  • Cannot upload to OneDrive using the new SDK
  • Read text file that is not in the main package in a runnable jar
  • How to revert to previous XCode version?
  • Ionic 2 storage is not cleaning up on uninstall - Only for signed APK
  • MVC3 Razor - ListBox pre-select not working
  • Email verification using google app script and google forms
  • Django rest serializer Breaks when data exists
  • How to use an array of arrays with array_map(…) in PHP?
  • How to rebase a series of branches?
  • Initializer list vs. initialization method
  • Is there any way to access browser form field suggestions from JavaScript?
  • Nant, Vault & Windows Integrated Authentication
  • Ajax jQuery multiple calls at the same time - long wait for answer and not able to cancel
  • req.body is undefined - nodejs
  • Azure Cloud Service Web Role web pages do not load
  • JavaScriptCore crash on iOS9
  • recyclerView does not call the onBindViewHolder when scroll in the view
  • Symfony2: How to get request parameter
  • what is the difference between the asp.net mvc application and asp.net web application
  • Hazelcast - OperationTimeoutException
  • How to get next/previous record number?
  • Akka Routing: Reply's send to router ends up as dead letters
  • SVN: Merging two branches together
  • Confusion with PayPal's monthly billing cycle
  • Is there a mandatory requirement to switch app.yaml?
  • Transpose CSV data with awk (pivot transformation)
  • File upload with ng-file-upload throwing error