i was reading about the buffering of contents and i found a simple script to show effects of flush
<?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();
?>
this script works fine and show the output , but when i remove the str_pad or reduce the length from 4096 to 40 flush does not work.
can any one help me out what exactly causing this..
Atlast i found the reason.
According to PHP.net Broswers require certain bytes to start the display of the page. Like some version of Internet Explorer require 200 bytes. And modern broswers like Firefox or Chrome requires more bytes to start Browser display.
In above case if you check it in Internet Explorer it will not require string padding but in Firefox or Chrome you need to Padd spaces with input to display flushed output.
I recognize this problem, had it once myself.. Do you have output compression activated?
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 wrote this code to check the live sequence in which actual code runs in php
header('Content-type: text/html; charset=utf-8' );
echo 'Begin ...<br />';
flush();
ob_flush();
echo "Hello<br />";
flush();
ob_flush();
sleep(5);
The expected output should be in this order :
1. Begin
2. Hello
3. sleep(5)
But the order in which they are actually executed is :
1.Begin
2.sleep(5)
3.Hello
If php is really sequential then it should follow the sequence given then why this difference ? And if i want to execute commands strictly in the sequence then what is the procedure as I need it for updating progress bar width.
You can check this behaviour by commenting the sleep function it won't wait between Begin and Hello also.
Iam using codeigniter framework.
In most cases flushing alone is not enough, the Browser needs at least I think it was 256kb of data, in some browsers at least but it depends and changes, before it SHOWS the flush, so it is fluesh but you do not see the result, try something like
echo "Hello<br />";
str_repeat(" ",256);
I know it is too much but it should work, then you should see what you expect
you can play with the number if it is not what you expect, as I said it also depends on the used browser :D
I faced a strange issue today.
For several months I used buffer flushing in PHP to send small string sizes to the client without problems.
Today I returned to the project and it turned out that my server won't send strings smaller than 512 bytes.
Here is my code:
<?php
echo "length:".$myUpcomingStringSize;
ob_flush();
flush();
sleep(1);
for($i = 0; $i < count($allLines); $++) {
echo $allLines[$i];
ob_flush();
flush();
}
?>
This code worked like charm the whole last year. And now it doesn't anymore. I played around a bit and added some random characters. As the string size gets equal or greater 512, the server sends the buffer content.
Can anybody imagine the issue I have to solve here? Anyone else facing this issue? Or does
someone know how to configure this minimum packet size?
If you changed neither the program nor the server, you should assume that the program never worked as intended. Especially Windows systems are known to buffer the output until a certain number of Bytes is in the output buffer. This buffering is at system-level and thus can not be affected by any PHP configuration.
If you know that 512 Bytes is the minimum required for the output buffer to send, then you could use something like
define('MIN_OUTPUT_LENGTH', 512);
echo str_pad("length: $myUpcomingStringSize", MIN_OUTPUT_LENGTH, "\0"), '\n';
// (If you run into trouble with the null-bytes, use space character instead)
Notes
If you do not use "userspace" output buffering, then ob_flush(); is redundant.
If there is no delay in your for loop, then flushing between lines is not a good idea. Especially for mobile applications where the network tries to pack as much data as possible into a single packet.
There is a syntax error in your for loop header (The expression $++ is missing a variable identifier, probably i)
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.
I have a php script that is running in CLI and I want to display the current percent progress so I was wondering if it is possible to update the STDOUT to display the new percent.
When I use rewind() or fseek() it just throws an error message.
See this code:
<?php
echo "1";
echo chr(8);
echo "2";
The output is only 2 since "chr(8)" is the char for "backspace".
So just print the amount of chars you need to go back and print the new percentage.
Printing "\r" works too on Linux and Windows but isn't going to cut it on a mac
Working example:
echo "Done: ";
$string = "";
for($i = 0; $i < 100; ++$i) {
echo str_repeat(chr(8), strlen($string));
$string = $i."%";
echo $string;
sleep(1);
}
Output \r and then flush to get back to the first column of the current line.
Writing to a console/terminal is surprisingly complex if you want to move backwards in the output raster or do things like add colours - and the behaviour will vary depending on the type of console/terminal you are using. A long time ago some people came up with the idea of building an abstract representation of a terminal and writing to that.
See this article for details of how to do that in PHP.