10

I have a php script that uses cURL and takes about 10-15 minutes to execute. What it does, it parses about 1000 pages looking for specific matches and throughout the script I have diagnostic messages echo'ed out, like "Going to the next page", "Found a match", "Error loading page" ... The way it works now (and the way that it's normal) is it executes for like 10 minutes and only then spits out all my custom messages. I would like to be able to display those messages as they happen, not when the script is done executing. I was thinking something like AJAX would do it, but am not sure how it would work. Any tips are greatly appreciated. Thanks.

pHelics
  • 293
  • 1
  • 4
  • 7
  • 1
    Similar to [this question](http://stackoverflow.com/questions/4481235/php-flush-ob-flush-not-working). – netcoder Jan 12 '11 at 14:28
  • One other simple case would be to execute the script from the command line , that way you will get you're echo's in real time . – Poelinca Dorin Jan 12 '11 at 14:28

9 Answers9

12

So, this is a old post but I found a solution for this. As I also have to make the same thing, output when the script is still running. Not any answer from here helped. First of all, I am using Win32 server(production) and XAMPP as local for tests. This example is just a proof of concept and can be modified as you please.

<?php 
ob_implicit_flush(true);
for($i=1; $i<=10; $i++){
echo "$i ...<br>";
for($k = 0; $k < 40000; $k++) echo ' ';
sleep(1);
}
?>

So, we open output buffer as implicit. Then we make a demo loop to count from 1 to 10 and display the values as they are been processed. Second loop will fill in the browsers buffer. And finally to check if everything is working well we make a sleep for 1 second. Otherwise the script will run too fast and we could not know if we achieved the goal. Hope this helps !

Bogdan
  • 136
  • 1
  • 2
7

You could create a staging table.

The PHP script could, instead of echo'ing the message, store them into a database table (possibly memory table for performance).

You could then periodically poll a seperate PHP script using ajax, which would query the table, and return any new messages to the client.

Mads Mogenshøj
  • 2,063
  • 1
  • 16
  • 23
6

Use flush to immediately send output to the browser, by flushing the output buffer.

echo "foo";
flush();
echo "bar";
flush();
karim79
  • 339,989
  • 67
  • 413
  • 406
3

Actually you're looking for something like flush and ob_flush, however bear in mind that there are a lot of factors that can prevent your output from being flush'd as it happens.

From the flush documentation you'll get:

Several servers, especially on Win32, will still buffer the output from your script until it terminates before transmitting the results to the browser.

Server modules for Apache like mod_gzip may do buffering of their own that will cause flush() to not result in data being sent immediately to the client.

Community
  • 1
  • 1
acm
  • 6,541
  • 3
  • 39
  • 44
  • You made a good point, until the script is done I'm working on it on Win32 platform, then I'll put it to unix – pHelics Jan 12 '11 at 15:45
1

I'm using the @ob_flush() after every echo. In this example PHP_EOL creates a new line after $string

function output($string){
    echo $string.PHP_EOL;
    @ob_flush();
}
Walter White
  • 359
  • 3
  • 17
0

You could use both flush and ob_flush, reminding to set the content type header:

<?php
header( 'Content-type: text/html; charset=utf-8' );
for( $i = 0 ; $i < 10 ; $i++ ){
    echo $i . '<br>';
    flush();
    ob_flush();
    sleep(1);
}

Source: dermeister note in php.net ob_flush page.

Tested on Firefox 42.0 and Chrome 46.0

T30
  • 11,422
  • 7
  • 53
  • 57
0

Basically, have your script write HTML output to a temporary log file. Then use ajax to periodically update the end-user's browser with the temporary log file. jQuery will make quick work of this.

Ajax is the only guaranteed way to get it to work on all browsers. Here is a quote from PHP's flush page.

flush() may not be able to override the buffering scheme of your web server and it has no effect on any client-side buffering in the browser. It also doesn't affect PHP's userspace output buffering mechanism. This means you will have to call both ob_flush() and flush() to flush the ob output buffers if you are using those.

mrbinky3000
  • 4,055
  • 8
  • 43
  • 54
  • what if there will be 1000 users accessing the page at the same time with different parameters ? , you'll need to write 1000 files , i don't see this as an option . – Poelinca Dorin Jan 12 '11 at 14:30
  • You can easily create temp files in PHP. Its basically the same as a 1000 users INSERT'ing stuff into a mysql database. Heck, use, mysql. Just store a log someplace and tie it to that session if more than one person is using it. I have a feeling this is a backend script to be used by a single person. – mrbinky3000 Jan 12 '11 at 14:33
0

Sounds to be like you have output buffering turned on.

Calling ob_end_flush() will print what's currently in the buffer, and turn off the buffer for the rest of the script execution.

Craige
  • 2,882
  • 2
  • 20
  • 28
0

You can use the flush() function to send all the content of the buffer to the client. http://php.net/manual/fr/function.flush.php

N. Hodin
  • 1,056
  • 6
  • 12