Organizational Research By

Surprising Reserch Topic

continue php script after connection close


continue php script after connection close  using -'php,codeigniter,output-buffering'

I am trying to continue a PHP Script after the page/connection is closed.

Users will POLL the script in every 1 hour, I want to return some json output and want to continue the script in the background. I am using a shared host and I cannot use cron job.

Here is what I've tried.

ob_start();

ignore_user_abort();

echo "JSON_OUTPUT GOES HERE";

$ob_length = ob_get_length();

header("Content-Type : text/plain",TRUE);
header("Content-Length : $ob_length",TRUE);
header("Connection : Close",TRUE);

flush();
ob_flush();
ob_end_flush();

sleep(3);

echo "You cant see me..";

exit();


I am using Codeigniter framework, But its not working on my live server. It waits 3 seconds and then outputting You cant see me.. too.

Please help me.

Note

Project is hosted in LINUX/WINDOWS/WAMP-SERVER shared hosts.
    

asked Sep 15, 2015 by Courtney87Z
0 votes
12 views



Related Hot Questions

3 Answers

0 votes

After some research i got it work, Sometime it may be useful to some others.

function closeOutput($stringToOutput){   
        set_time_limit(0);
        ignore_user_abort(true);
        header("Connection: close\r\n");
        header("Content-Encoding: none\r\n");  
        ob_start();          
        echo $stringToOutput;   
        $size = ob_get_length();   
        header("Content-Length: $size",TRUE);  
        ob_end_flush();
        ob_flush();
        flush();   
} 

You can use it like

$outputContent = 'Contentent Goes Here...';

closeOutput( $outputContent );

sleep(5);

//do some background works ...

exit();
answered Sep 15, 2015 by IslaDonohuei
0 votes

First, don't use space after Connection and before : it should be Header: value not Header : value. Second, Connection: close don't force browser to stop getting current response and display blank page. Here http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html chapter 14.10 it states: Connection: close in either the request or the response header fields indicates that the connection SHOULD NOT be considered 'persistent' (section 8.1) after the current request/response is complete

So how can you try if your code works:

ignore_user_abort();
header("Content-Type: text/plain; charset=UTF-8");

// just to try show following echo immediately, working depends on server configuration
while (@ob_end_flush()); 

echo date('Y-m-d H:i:s'), PHP_EOL;

echo "JSON_OUTPUT GOES HERE", PHP_EOL;

sleep(10); // 10 seconds so you can close browser tab before

// this file should be created after 10 seconds, even after you closed browser tab
// also check if permissions to write to __DIR__ are set for apache.
file_put_contents(__DIR__ . '/tmp.txt', "Text after 10 sec");

exit;

Open this php file in browser and after 2-3 seconds close tab (even if you don't see anything on screen), wait a little longer and check if file is created. It's working on my linux machine.

answered Sep 15, 2015 by TaniaScarber
0 votes

Because of this cool possibility, which Red posted, I've written a small utility class which provides a queue where you can add Closures for later execution:

 $task,
        'arguments' => $arguments
    );
}

/**
 * Returns TRUE if tasks has been set, otherwise FALSE
 *
 * @return boolean
 */
public static function hasTasks() {
    return !empty(self::$tasks);
}

/**
 * Clear all previous set tasks
 *
 * @return void
 */
protected static function clearTasks() {
    self::$tasks = array();
}

/**
 * Execute all previous set tasks
 *
 * @return void
 */
protected static function executeTasks() {
    foreach (self::$tasks as $task) {
        call_user_func_array($task['closure'], $task['arguments']);
    }
}

/**
 * Execute and clear all previous set tasks
 *
 * @return void
 */
public static function executeAndClearTasks() {
    self::executeTasks();
    self::clearTasks();
}

/**
 * Closes the HTTP connection to client immediately and outputs given string.
 *
 * @param string $instantOutput
 * @return void
 */
public static function closeConnection($instantOutput = '') {
    set_time_limit(0);
    ignore_user_abort(TRUE);
    header('Connection: close' . self::HEADER_NEW_LINE);
    header('Content-Encoding: none' . self::HEADER_NEW_LINE);
    ob_start();
    echo $instantOutput;
    $size = ob_get_length();
    header('Content-Length: ' . $size, TRUE);
    ob_end_flush();
    ob_flush();
    flush();
}
}

This is how you add new tasks to queue:

use Company\Project\Utilities\ContinueUtility;

$a = 4;
$b = 5;
ContinueUtility::addTask(function($a, $b){
    sleep(5);
    $c = a + b;
    file_put_contents(__DIR__ . '/whatever.log', $a . '+' . $b . '=' . $c);
}, array(
    $a, $b
));

And this is how you trigger execution of all previous added tasks:

ContinueUtility::closeConnection('Ready.');
ContinueUtility::executeAndClearTasks();
answered Sep 15, 2015 by Lori7213tarh

...