I need a fix for this.here is just part of my code
<?php
$number = 30;
while($number > 0) {
$number--;
sleep(30);
print "$number . Posted<br>";
}
?>
The loop process in the loop is actually much bigger, i just put the important stuff.
Anyways as you can see it should print
30 posted
(wait 30 seconds)
29 Posted
(wait 30 seconds)
28 Posted
(wait 30 seconds)
But instead it waits till the loop is over, then just prints it all at once. Is there a fix for this? I was thinking an ajax method, but I dont know of any.
Nice that everyone explained why.
This is because by default PHP will process everything before it 'flushed' anything out to the browser. By just printing each line, it's storing that information in the buffer which will all be printed simultaneously once PHP is finished executing.
If you want PHP to flush that content to the browser immediately after the line, you need to call flush() after each one, then it will output the text one line at a time after each one is called.
Call flush() after printing.
You need to use flush()
An example of a loop with flush() is
<?php
ob_start();
for ($i = 0; $i < 10; $i++)
{
echo "<div>" . time() . ": Iteration $i</div>";
sleep(1);
ob_flush();
flush();
}
ob_end_flush();
?>
You should not flush often because you force php to process messages and this will increase the time of execution.
You might put \n in echo or print to flush the buffer.
Related
I have a loop and each iteration takes N seconds.
for($i=0;$i<10;$i++) {
echo $i;
process(); // 10 seconds process
}
Is there a way to output progressively (in web page) $i without having to wait until the whole loop ends ?
Flushes the system write buffers of PHP and whatever backend PHP is using (CGI, a web server, etc). This attempts to push current output all the way to the browser with a few caveats.
<?php
if (ob_get_level() == 0) ob_start();
for ($i = 0; $i<10; $i++) {
echo "<br> Line to show.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
sleep(2);
}
echo "Done.";
ob_end_flush();
?>
Read documentation here.
EDIT:
str_pad() - Pad a string to a certain length with another string.
and Some versions of Microsoft Internet Explorer will only start to display the page after they have received 256 bytes of output, so you may need to send extra whitespace before flushing to get those browsers to display the page. that's why use str_pad() for be safe side.
I am creating simple script to test that I can echo inside my while loop before it gets 60 seconds,but the problem is it will not echo inside my loop.I don't know if it is really executed inside my while loop. Then my browser will crashed.
$timelimit = 60; //seconds
set_time_limit($timelimit);
$start_time = time(); //set startup time;
while(((time() - $start_time) < $timelimit) || !$timelimit){
echo "executing..<br/>";
}
Thank you in advance.
This is a very tight loop. It will run very fast and will create a very large output, which will eventually kill the browser (it will have hundreds of thousands of lines). You may add some delay to your loop:
while(((time() - $start_time) < $timelimit) || !$timelimit){
sleep(1); // pause for 1 second
echo "executing..<br/>";
}
In this case the output will be only 60 lines, and the browser should render it after a minute of waiting.
CPU execution is very first (approximately 10^-9s per execution). Your looping time is 60 seconds. So consider how many (may be 300915626 executions) executions will occur. During this time if you want to print something your browser will be killed.
If you're expecting to see the output as the script generates it, then you'll want to add a flush(); after your echo. However, if I recall correctly, php will still wait to send the output until it has a certain number of bytes (1024 maybe?)
I just want to print a counting from 1 to 10 at an interval of 10 sec between each integer.
eg.
$i=10; //Time delay
for($j=1;$j<11;$j++)
{
echo $j;
//do something to delay the execution by $i seconds
}
I have tried everything including flush(), ob_flush(), ob_implicit_flush() but all i get is a frozen screen untill the whole time is executed.
http://php.net/manual/en/function.sleep.php
The sleep function will interrupt execution of your script.
But have you considered using Javascript for something like this? Your script may reach maximum execution time, and will be hogging resources on the server. Use the client's resources instead!
What you want is much more javascript-related than PHP. Because PHP is serverside it is not designed to do these kind of operations. You COULD get it to work, but it would not be very pretty.
In my logic; counting from 1 to 10 should not involve the server at all. You can do this directly in the browser, hence use javascript.
you want to print the countdown while your php script is running?
if yes, then try that non-recommended fragment:
ob_start();
for($i=0;$i<10;$i++) {
echo str_repeat(" ",10000);
echo 'printing...<br />';
ob_flush();
flush();
sleep(1);
}
you see, the strange line:
echo str_repeat(" ",10000);
it seems that browsers needs some "data" before deciding to really flush your data.
Use javascript for real time counters.
Use jQuery. On $(document).ready add a delay of 10 seconds to show a specific div which would contain the info to appear after 10 seconds.
For ready - http://api.jquery.com/ready/
For delay - http://api.jquery.com/delay/
Yes, use Javascript as it's not possible to accomplish this task with PHP using HTTP because of output buffering.
I'm developing a long running php script that compiles scraped information from multiple sources, organizes them, and caches them in a database.
As this script has a very high runtime, I'd like to print out runtime status reports in order to track the progress.
for ($i = 1; $i<= 10; $i++) {
echo "Starting iteration #$i\n";
set_time_limit(40);
echo "Time Limit set, starting 10 second sleep.\n";
sleep(10);
echo "Finishing iteration #$i\n\n";
}
echo "Iterations Finished.";
would output:
Starting iteration #1
Time Limit set, starting 10 second sleep
then wait 10 seconds and output:
Finishing iteration #1
Starting iteration #2
Time Limit set, starting 10 second sleep
then right before the php finishes parsing, it will output:
Iterations Finished.
What is the best way to achieve this?
If you are running PHP from the CLI you can output directly to stdout, without having to wait for the script
to end, using :
$handle = fopen('php://stdout', 'r');
fwrite($handle, $output);
If run from CGI, which would be really bad for a script like this, you would have to change how the buffer acts with flush();
Try writing the runtime status reports to a file, then viewing live updates of the file using ajax, per this question: Live feed of an updating file
I want to read everything from a textfile and echo it. But there might be more lines written to the text-file while I'm reading so I don't want the script to exit when it has reached the end of the file, instead I wan't it to wait forever for more lines. Is this possible in php?
this is just a guess, but try to pass through (passthru) a "tail -f" output.
but you will need to find a way to flush() your buffer.
IMHO a much nicer solution would be to build a ajax site.
read the contents of the file in to an array. store the number of lines in the session. print the content of the file.
start an ajax request every x seconds to a script which checks the file, if the line count is greater then the session count append the result to the page.
you could use popen() inststed:
$f = popen("tail -f /where/ever/your/file/is 2>&1", 'r');
while(!feof($f)) {
$buffer = fgets($f);
echo "$buffer\n";
flush();
sleep(1);
}
pclose($f)
the sleep is important, without it you will have 100% CPU time.
In fact, when you "echo" it, it goes to the buffer. So what you want is "appending" the new content if it's added while the browser is still receiving output. And this is not possible (but there are some approaches to this).
I solved it.
The trick was to use fopen and when eof is reached move the cursor to the previous position and continue reading from there.
<?php
$handle = fopen('text.txt', 'r');
$lastpos = 0;
while(true){
if (!feof($handle)){
echo fread($handle,8192);
flush();
$lastpos = ftell($handle);
}else{
fseek($handle,$lastpos);
}
}
?>
Still consumes pretty much cpu though, don't know how to solve that.
You may also use filemtime: you get latest modification timestamp, send the output and at the end compare again the stored filemtime with the current one.
Anyway, if you want the script go at the same time that the browser (or client), you should send the output using chunks (fread, flush), then check any changes at the end. If there are any changes, re-open the file and read from the latest position (you can get the position outside of the loop of while(!feof())).