Making PHP Connection handling work for you
Recently i had a challenge where i needed to return a hyper fast response with data to the user (browser), although due to the number of operations needed to perform on database that was just not possible. So, i did some research, and remembered a technique that Bruno Pedro pointed out awhile ago.
If you play a little bit with Php and http headers you will make possible to:
- Return data to the browser
- Detach http server process from client (browser)
- Keep script execution running
The solution is actually quite simple, if you refer to PHP Manual – Connection handling section, you will find a lot of examples on how to do this.
As a small exercise i designed a small script that illustrates this behavior, you can download it from my Google Code project repository.
<?php /** * Here is where the magic happens * Let's play with browser connection headers to detach connection */ ob_end_clean(); header("Connection: close"); ignore_user_abort(); ob_start(); /** * Making the stuff that can't be postponed and is needed for user response * In here you should add the real-time processing code */ require_once "Processer.php"; $processer = new Processer(); echo $processer->process(); /** * Sending the headers and releasing the connection */ $size = ob_get_length(); header("Content-Length: $size"); ob_end_flush(); flush(); /** * Now that response was returned to user lets perform heavy operations / calculations * All the code below this comment will be processed without having the browser waiting for response */ $processer->processDelayed();
HTTP/1.1 defines the “close” connection option for the sender to signal that the connection will be closed after completion of the response. in W3.org
Calling this function will avoiding that if user presses the STOP button on browser the script terminates, this instruction makes the process independent from this user action.
Using the examples code, you can notice that the browser receives the response right away without any heavy processing, although processing keeps running on http server process.
You can check out processing time differences on the examples log file, by default is stored on /tmp/utime.log.
I used a custom designed Processer controller, to exemplify the behavior, although you can just substitute the Processer usage by simple php code blocks that will have the exact same behavior.