Why php is not running following order of commands in sequence? - php

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

Related

What is the use of the ob_get_length() method?

i know those methods related to output buffering:
<?php
ob_start();
// some code
ob_end_flush();
ob_end_clean();
but i can't figure out why will i need the length of the output buffer. there is one question here is SOF about measuring the bandwidth of the user ,although that calculation will need to measure pictures and other files which is not addressed.
i did check the PHP manual and the "why" is not there.
Answering "why to use it". In order to answer this, we must first understand why we need to use ob_start.
Usually it is used for two purpose:
When we want to send HTTP headers, but we are not sure, that there is no rendering before(the first output will trigger header sending, so if you use, echo for example, before header, the later won't work)
When we want to send our output by chunks for performance. (your code can be written with a lot of echo or print, and usually they outputing only small data, so you are sending small portions of data back to browser, which is affecting performance.)
So now you can start to guess, why we need to use ob_get_length(). For example: i want to send my output by large chunks, so i am enabling output buffering and with the help of ob_get_lengthi can control how many data i can write to buffer, before sending it.
ob_get_length will return the length of the contents in the output buffer..
Here is simple example..
<?php
ob_start();
echo "Hello ";
$len1 = ob_get_length();
echo "World";
$len2 = ob_get_length();
ob_end_clean();
echo $len1 . ", ." . $len2;
?>
The above example will output: 6, 11
Updated:
ob_get_length() is helpful if you want to send a custom HTTP Content-Length header - although that is for advanced users only!

How to NOT print a trailing newline after echo "<something>"

For a command line application I am trying to ask a simple question using the following code (example is not real life, code, but resembles the "real" version):
echo "Do you want to quit? [Y]/N";
$handle = fopen ( "php://stdin", "r" );
$input = trim(fgets($handle));
if ( empty($input) ) {
$input = 'Y';
echo "Y\n";
}
The result I want, is the following - When a user does -NOT- provide input:
Do you want to quit? [Y]/N: N // User only hits enter, not 'N'..
What I get is:
Do you want to quit? [Y]/N: // User only hits enter, not 'N'..
N
So the question is: How do I force echo 'Something'; to NOT print a newline after the echo.
Basically I need the equivalent of bash's echo -n '...' (does not print the trailing newline).
To understand why is it so - you need to understand that there are two things: STDIN and STDOUT that are involved into program. And - yes, php does not add new lines. With simple echo "foo"; you'll get exactly "foo", without new line.
But why are you seeing new line then? Simple: because you've pressed "it". That is: you've pressed "enter" key, terminal got it and printed it. Your program, of course, also got it, but at that moment the "key" is already printed.
What can you do? On that step: nothing. It's already done and that's it. You'll see it in your screen. However, yes, there is a trick that I can suggest. You can use stty to maintain behavior, when you can control the input and/or output. Combined with system() you'll get the idea.
Here we are with code:
function emulatePrintable()
{
$result = '';
while($c = trim(fgetc(STDIN)))
{
echo($c);
$result.=$c;
}
return $result;
}
system('stty -echo');
echo("Do you want to quit? [Y]/N ");
$result = emulatePrintable();
if($result==='')
{
echo("You didn't type anything!");
}
echo "\n"; //<--- this is to delimit program's end of work
system('stty echo');
What's happening? You're doing this:
Suppress any input printing with stty -echo. This is the trick. You're suppressing only input display, not output display. That is why you'll be able to see echo() strings from PHP
Emulating output for printable characters. That is: you still want to show what user is typing (your Y or N) - but you want to skip new line. Simple emulatePrintable() will do the work (may be not the best name, but at least I've tried)
After you've got the input (it's interrupted with EOL, for example) - you can examine what is it. If it's an empty string, then you've caught it: user typed nothing.
Now, do not forget to enable input display with stty echo - otherwise.. well, you'll end with "non-working" terminal.
Benefit: with this you'll be able even to decide, to print character or not (for example, to restrict only Y and N for output).
So this is the solution for unix-based OS. In Win - best of luck to you. You may check this page for console modes & related stuff, but I'm not sure it will work (since have not tested).

PHP - Unbuffered While() Loop

I am using php, I see while() loop in php. I want to ask something can we use
while() loop as mysql_unbuffered_query().
This code make good understanding.
<?php
echo 'While Loop is going to start';
$i = 0;
while($i <= 1000){
echo 'Now number is '.$i;
$i++;
}
echo 'Continue to running script';
?>
What happens when we run this code first of all this code read while loop is going to start
then read the while loop and create the statement to run Now number is 0.....1000
then read Continue to running script And when the code is finished it print out whole data.But I did not want this.
What I want.
First script read the while Loop is going to start and print out then read while loop and
print out Now number is 0 then go Continue to running script and print out But the
back end of script while loop still working, My mean both while loop and continue script working at once.
This give you more understanding.
OUTPUT(First time when script running is start)
1 - While Loop is going to start
2 - Now number is 0
3 - Continue to running script
OUTPUT(Script running is continue)
1 - While Loop is going to start
2 - Now number is 0
3 - Now number is 1
. - ...............
1000 - Now number is 1000
1001 - Continue to running script
Might be this is impossible.If yes how I can do that.
But maybe this is possible like mysql_unbuffered_query().
Like when while loop complete one cycle it print out the number and then other one and so on to complete.
OUTPUT(First time when while loop complete one cycle)
1 - While Loop is going to start
2 - Now number is 0
OUTPUT(while loop complete second cycle)
1 - While Loop is going to start
2 - Now number is 0
3 - Now number is 1
If this is possible, Please guide me how can I do that.
Thanks..............
If you are running this script from the command line, output buffering is always off, and implicit flush is always on (according to http://us3.php.net/manual/en/outcontrol.configuration.php ). Because of this, I suspect you are running this PHP within a web server.
There are several PHP INI values which affect buffering, so you may wish to turn off these features:
<?php
ini_set('zlib.output_compression', 'off');
ini_set('implicit_flush', 'on');
ini_set('output_buffering', 'off');
echo "While Loop is going to start.\n";
$i = 0;
while($i <= 10){
echo "Now number is ".$i."\n<br>\n";
$i++;
sleep(1);
}
echo "\n<br>Finished running script\n\n";
?>
Even after all that, it's possible that PHP is behaving exactly as you want, but your web server is buffering the output. This thread may be of interest: php flush not working
If you are using apache, you can add a line to an .htaccess file to turn off gzip compression (which automatically buffers until there's enough data to compress and send)
I found this page (http://www.bluehostforum.com/showthread.php?18996-Turning-off-Gzip) which describes the process, but it basically says to add
SetEnv no-gzip dont-vary
to your .htaccess file.
Can you confirm that the script I posted above works as you'd expect in your command line environment or not?
Also, if you are working within a web server, please post which web server you're using (IIS/apache/etc)
You need threads or processes. This is a good thread: Does PHP have threading?
My favorite answer there is https://stackoverflow.com/a/14201579/650405
Forcing output to the browser works with the following calls in this order
ob_flush();
flush();
It, however, will not background any processing going on.

PHP Output Buffer "Millenium" Bug?

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)

ob_flush takes long time to be executed

In my website(running with drupal) the ob_flush function takes a long time(between 10 - 100 secs) to be executed. How do I find out why? What can cause this so long time?
Try this:
ob_start();
//Your code to generate the output
$result = ob_get_contents(); //save the contents of output buffer to a string
ob_end_clean();
echo $result;
It is run quick for me.
[You may want to tag your question with Drupal, since this feels like it might be a Drupal issue. Specifically, I suspect that when you flush the buffer, you're writing to an outer buffer, which triggers a ton of hooks to be called to filter the data you've just written.]
I suspect that your problem is nested buffers. Drupal really likes buffers and buffers everything all over the place. Check the result of:
echo "<pre>\nBuffering level: ";
. ob_get_level() .
. "\nBuffer status:\n"
. var_dump(ob_get_status(TRUE))
. "\n</pre>";
If you've got nested buffers, then I suspect ob_flush() will do nothing for you: it just appends the contents of your inner buffer into the next outermost layer of buffering.
Nested buffers can come from Drupal itself (which the above will show), or from the settings for zlib-output-compression and output_buffering (try twiddling those, see if it changes anything).
If your buffers are not nested, and the above settings do not help, then you may also want to split the operation into pieces, and run the profiler there, to see which part is taking the time:
$data = ob_get_contents(); // Return the contents of the output buffer.
ob_clean(); // Clean (erase) the output buffer.
ob_end(); // Close the buffer.
echo($data); // Output our data - only works if there's no outer buffer!
ob_start(); // Start our buffer again.
The question then becomes, though, "what are you trying to accomplish?" What do you think ob_flush() is doing here? Because if the answer is "I want to push everything I've done so far to the browser"... then I'm afraid that ob_flush() just isn't the right way.
SET
output_buffering = Off
in php.ini
use
<?ob_start();?>
at the beginning of the page and
<?ob_flush();?>
at the end of the page, to solve this problem.

Categories