在脚本之间实现共享变量或如何实现服务器端进度的正确方法?

I have a long job serving to fill a table in a db. This job may takes various time to finish. So, I need a progress bar. Just counting on the page is enough. As far I found several solutions:

  1. Using _SESSION. OK, it works on most of servers I used, but I have many problem with ERR_RESPONSE_HEADERS_TOO_BIG error on chrome and sometimes - "headers already sent" on some servers, caused by session_start/session_write_close called in a loop. I loved this method but now I have reject it
  2. Using kind of ob_start/ob_end_flush inside of the long operation's loop. This doesn't work. It just displays all buffered echo-ed messaged after the end of script.
  3. Using db to store a shared variable (not tried yet)
  4. Using separate (temporary) file. (not tried yet).

I have already implemented infrastructure: one script for long job (populating a table in db) and another one used by JS to read shared variable containing progress status. Both these scripts I called with jQuery .ajax method expecting the results in .done function.

Is there any other methods? It seems I will like to use 4) variant, but I want to know what is the usual practice for implementing progress bar.

Thanks:)

Firstly, if you aren't already, I would run the PHP code as a separate process.

 <?php 

 exec('/usr/bin/php /Path/to/script.php  {$param1} {$param2} > /dev/null 2>/dev/null &'); 

 ?>

I would then get this process to update a DB with its progress against the ID of the user, you could then use a ajax call inside a timeout function to get the status (how many DB writes complete, how many left, etc) from the DB.

Well using session is the way to go but what if user accidentally closes browser? Then progress bar will reset to its initial state. Also the error that you are getting is because you are echoing html before headers are sent.

So the best way to go in my opinion is to store progress in a table (database) and each time user visits a page pull it out of table and display it how much % of the work has been completed.

Steps:

1. Default State In Table: 0 - indicates that user has not filled out anything 
2. User Fills out page 1 update progress in table: 1 - indicates user completed page 1
3. User Fills out page 2 update progress in table: 2 - indicates user completed page 2

to display this in percentages do following:

$total = 3; //total pages that user needs to fill out
$filledOut = $db->getUserProgressStatus(); //return the digit status of user progress
$percent = ($filledOut / $total) * 100; //gives you % value 

so this is what values you get on each page:

Page 1: (0 / 3) * 100 = 0%
Page 2: (1 / 3) * 100 = 33% //first page completed
Page 3: (2 / 3) * 100 = 67% //second page completed
Page 4 (summary page): (3 / 3) * 100 = 100% //completed
function fcflush()
{
    static $output_handler = null;
    if ($output_handler === null) {
        $output_handler = @ini_get('output_handler');
    }
    if ($output_handler == 'ob_gzhandler') {
        // forcing a flush with this is very bad
        return;
    }
    flush();
    if (function_exists('ob_flush') AND function_exists('ob_get_length') AND ob_get_length() !== false) {
        @ob_flush();
    } else if (function_exists('ob_end_flush') AND function_exists('ob_start') AND function_exists('ob_get_length') AND ob_get_length() !== FALSE) {
        @ob_end_flush();
        @ob_start();
    }
}

//infinite loop example of usage
$counter = 0;
while (true) {
    echo $counter."<br />";
    fcflush();
    $counter++;
}