At my wits end on sleep() - php

I've got sleep(n) in a loop that is intended to do output on a periodic cycle.
But when I run the loop, nothing happens until all of the seconds in the intended loop duration accrue collectively, after which all of the output comes spilling out at once.
Help. Thanks.

try that:
ob_end_flush (); // just in case
while (1) {
echo 'wait for it<br/>'.PHP_EOL;
flush ();
sleep (2);
}

Maybe you need to flush() the output buffer after each piece of output?

Argh, the site's not letting me add comment to mathroc's latest. So I'll put it here:
It didn't work for me. But the following is really weird: I accidentally stumbled upon some other sleep code on the web that I stuck in front of what I've got:
<HTML>
<BODY>
$c=0;
while($c <$chunks){
$rand = rand(2000000, 6000000);
echo '<br> . . . sleeping for ' . round(($rand / 1000000),2) . ' seconds . . . zzzzzzzzzzzzzz<br>';
flush();
usleep($rand);
$c++;
}
WHAT I'VE GOT BEGINS HERE:
<br />
<br />
This page is loading.<br />
<?php
for($i=0;$i<5;$i++){
flush(); sleep(2);
?>
Almost there...<br />
<?php
}
?>
<?php flush(); sleep(2); ?>
Done.<br />
</BODY>
</HTML>
...and now the lower block of code sleeps fine, sequentially. Output is properly staggered (instead of arriving all in a lump at the end of 10 secs).
It's weird because I don't know what the above is doing that would make everything in the block below work all right. If I remove it, my block doesn't work (i.e., the output accumulates and then spills en masse at the end). If I remove only bits and pieces of the code above, then my thing wants to jump forward a little (but sequentially outputs the rest fine).
I have no idea what the preceding code is doing that makes my (latter block) work the way it should, or how to abbreviate it so that it still makes the latter block fully work, or even how to make the above code invisible on the page while still allowing the latter block to work accurately.
(I've tested the script on both Windows 7 Caucho Resin PHP 5 and Linux Apache CGI-BIN PHP 4 platforms. Identical results.)

It sounds like you should be using flush() instead of sleep().
http://us3.php.net/manual/en/function.flush.php

Related

Running A PHP File In Console And Clearing Echoed Results In A Loop?

I have a PHP file that currently runs via my console on my Mac. It's a private piece of software that interacts with an API via a loop that runs every x seconds.
At the minute Im am echoing out all information during each loop but the problem is within console it just repeats the content and appends it on to the previous. Is there a way of clearing all previous echoed results after each loop?
I thought I could use \r to replace the line but that doesn't seem to be working. I have also tried a few other examples after searching on here without any luck.
while(1){
echo "Some info goes here";
sleep(5);
}
For example if I try the following in a while loop
while(1){
echo "==============\r\n";
echo "==============\r\n";
sleep(5);
}
I end up with after a hand full of loops
Thanks
Two ways that I can think of off the top of my head:
Use the ANSI escape sequence to clear the screen:
print chr(27) . "[2J" . chr(27) . "[;H";
Run the command that clears the screen for your platform:
system("cls"); for windows
system("clear"); for unix-like systems
echo "\033[2J\033[;H";
Should clear your terminal.
If you just want to overwrite the same line again, this is working for me:
<?php
while(1) {
echo "test\r";
sleep(1);
}
?>

Uncontrollable Sleep? PHP

I understand how sleep works, But it works before something happens. Say for example I have a few echos and mail and some other things. Then have a sleep, then a redirect. Well, it looks like the sleep goes first, then everything just spam at once and cause server cpu increase. Is there something that is similar to sleep, that will not act after things have not been executed?
for example
echo 'Hey';
sleep(3);
echo 'My next text after 3 seconds is up';
well, with this, This does not work, and it does the same thing using C#.
When this happens, the page will not respond for 3 seconds, then both messages "Hey" & "My next text after 3 seconds is up" will show all at once. Is im using this for the wrong thing? Is there something else I should use?
Since I have never used sleep, and I seen alot of people use this for the same thing and it works, but in my case, it does not really works the way I thought it would.
PHP not C#
You can do it via flushing the output at points. You can also use ob_implicit_flush for this purpose which would ensure that output will be flushed at each output call without explicit calls for flush.
header( 'Content-type: text/html; charset=utf-8' );
echo 'Hey';
for($i=0;$i<60;$i++){
echo "<br />My next text after $i seconds is up";
ob_flush();
flush();
sleep(1);
}
Note that php docs for ob_flush suggests that you should try putting content-type header when things are not working. But above code worked without that also.
It runs exactly as it was programmed, the thing is, the output is being buffered. You have to disable buffering, and force a flush() to make sure its sent before the sleep().
while (# ob_end_flush()); // closes all existing buffers if any
echo 'Hey';
flush(); // make sure it was flushed to the client
sleep(3);
...
And still it might not work in all cases, because theres another buffer, and this one you cannot control: the browser. Some browsers will not render any HTML unless it has received a certain minimum amount of data.

PHP endless while loop confusion

I'm trying to figure out why this loop doesn't return anything to the browser:
while(1) {
echo "hello";
flush();
sleep(1);
}
I'm expecting it to return "hello" to the browser every second... am I wrong? Right now the page just seems to hang.
PHP only outputs after execution has finished. so all you are doing where is generating a new hello every milisecond, and since you never exit the loop, you never see the output.
To correct my answer and make you to understand better, and for the AJAX lovers...
you need and extra flush there.. the 'ob_' one:
<?php
while( 1 ):
echo "hello";
ob_flush( ); flush();
sleep( 1 );
endwhile;
This is the 'trick' for everyone who need to know ;)
The browser won't display anything until the entire page is received. PHP is not capable of what you're trying to accomplish.
In Javascript, this is pretty simple.
<script>
window.setInterval(function(){document.innerHTML += "<br> Hello"}, 1000)
</script>
You should realise that PHP is a scripting language in the sense that it returns the output only after completing the script. EDIT: Or after output buffers are filled, thanks #Marc B.
Regardless I would say it is wiser to use JS for this or if you really need your server, use AJAX requests.
Perhaps you should consider using Javascript? That will allow you to add content every second (do keep in mind that JS is run at the clientside though, so you might not want to make your operations all that expansive then.)
Alternatively you could consider using AJAX requests through for instance JQuery, but that might be outside the scope of this question...
Maybe is not to late to answer but if you want to flush every second here I give you a sample:
<?php
echo "Flushing every second ...\n";
flush( );
$seconds = array (0,1,2,3,4,5,6,7,8,9);
foreach ($seconds as $second):
echo $second . "\n";
sleep( 1 );
#ob_flush( ); flush( );
endforeach;
echo 'I flashed 10 second :P';
Valentin gave you the right answer (upvote him/accept his answer!), but didn't explain why. Here's the explanation:
Output buffering
PHP doesn't output to the browser immediately, it waits to have some amount of content to send to the browser (probably it sends in chunks of 1024, 2048 or 4096 bytes), or when the execution ends. Calling flush() makes PHP send the data, but there is more than one layer of buffering. One is the internal buffering (what I've just commented), but you can add more layers of buffering. Suppose this code:
<?php
echo "hi";
setcookie('mycookie', 'somevalue');
?>
The setcookie() function sends an http header to the browser, but it can't do it because in HTTP, the server (or the client, it is the same both ways) must send first all headers, a blank line, and then the contents. As you see, you are outputting some content (hi) before the header, so it fails (because the internal buffering follows the same order of execution).
You can add another layer of output buffering, using the php functions ob_*(). With ob buffering it only buffers content output, not HTTP headers. And you can use them to get the output of functions that directly output to the browser, like var_dump(). Also, you can nest layers of ob:
<?php
// start first level of output buffering
ob_start();
echo "nesting at level ", ob_get_level(), "<br />\n"; // prints level 1
echo "hi<br />";
ob_start();
echo "nesting at level ", ob_get_level(), "<br />\n"; // prints level 2
var_dump($_POST);
$post_dump = ob_get_clean();
// this will print level 1, because ob_get_clean has finished one level.
echo "nesting at level ", ob_get_level(), "<br />\n";
echo "The output of var_dump(\$_POST) is $post_dump<br />\n";
// in spite of being inside a layer of output_buffering, this will work
setcookie('mycookie', 'somevalue');
// flush the current buffer and delete it (will be done automatically at the
// end of the script if not called explicitly)
ob_end_flush();
Probably your PHP server has output_buffering enabled by default. See the configuration variables to turn it off/on by default.
Ok, Carlos criticize me because I didn't explained my answer but also his answer is to vague... with cookies, layers.. POST, ob_levels... :OO to much info with no real point about the real question of the user but I will tell you why your code is not working. Because you have set in the php.ini the output buffering something like:
output_buffering = On
or
output_buffering = 4096 (default setting on most distributions)
Thats why you need the extra 'ob_flush( )', to get rid of any garbage output..
so... To make your code work you have 2 options:
1). set output_buffering = 0 or Off (if you have access to the php.ini)
2). ob_flush many times as layers of buffering you have
If you don't know how many layers you have you can do something like:
while (#ob_end_clean( ));
and clean every garbage you can have, and then your code will work just fine..
Complete snipp:
<?php
while (#ob_end_clean( ));
while(1) {
echo "hello";
flush();
sleep(1);
}
Cya..
Adding to all the other answers,
To do asynchronous Server push to clients you'll need to use WebSockets. It's a vast subject and not fully standardized, but there are certainly ways of doing it. If you are interested search for PHP Websockets.

PHP Sleep Output before putting to sleep for next step

I am using SLEEP(). It seems the function works, but the script waits until all my sleep() functions have ran their course before the script displays any output.
Is there a way I can get output for for 1st and then it should wait and go to next ?
echo date('h:i:s') . "<br />";
//sleep for 10 seconds
sleep(10);
//start again
echo date('h:i:s'). "<br />";
//sleep for 10 seconds
sleep(10);
//start again
echo date('h:i:s');
I need output of 1st echo and then script should wait and give second echo ....and so on
Sleep Does not matter as for as output of the page is concerned. Page is served as soon as the last sleep is done... Though it stop processing of the page on server for the time of the sleep. .. in your scenario you should be using javascript for the affect.
You see, PHP runs completely on server-side, and sleep will just make the latency of the page more severe.
As Rab has suggested, try using JavaScript instead. It's not the same as Java (in fact, a lot different), and you might like to find some good tutorials online, or get some good books (the one from Murach is really good, trust me).

How to echo in PHP while the script is still executing?

I developed a facebook application in PHP. The problem is that it takes 2 minutes to display the result. This might confuse the user, who sees a blank canvas and leaves.
I just want to echo a statement that it is still processing.
I tried flush(); and ob_flush(); and ob_start(); but it is of no use.
Is there any other simpler alternative to address my specific problem?
I tried this, but it did not work as well.
ob_implicit_flush(true);
ob_end_flush();
for ($i=0; $i<5; $i++) {
echo $i.'<br>';
sleep(1);
}
EDIT:
The above code works perfectly fine with IE and other Browsers.
Only Chrome has this issue.
Convert it to an AJAX request, where you load a quick page which can have anything you want, and then loads in data from the slower page in the background.
flush() won't do what you want because it will return only part of the output and the client will tend to wait for the complete page.
Call flush(); as often as required.
Unfortunately, this might or might not make the browser feel happy to display your stuff. Even on IE, the result isn't predictable.

Categories