printing process output in realtime - php

I am using PHP 5.3.4 with Apache 2.2.17 on a Windows 7 x64 system. I would like to have my PHP page output the result of a system call in real-time to the user's browser. To that end, I have configured output_buffering=Off in php.ini and created this code:
<?php
ob_implicit_flush(true);
ob_end_flush();
system('ping -n 10 www.google.com');
?>
The result of the ping is printed in real-time, but I also get a PHP diagnostic error and callstack at the top of my page that says:
Notice: ob_end_flush() [ref.outcontrol]: failed to delete and flush buffer. No buffer to delete or flush in index.php on line 3
What do I need to do to either correct or suppress this error?
Update
If I change ob_end_flush() to $a = 1/0; I get a similar error and the output is realtime in all browsers. Is it something about the way the exception is printed that causes this to work?

some web browsers buffer the first x bytes before they start to render a page, under certain conditions.
try just outputting lots of whitespace first

I have a solution that works, but it is non-performant and icky. I throw an exception, but hide the exception dialog.
<?php
ob_implicit_flush(true);
// Something about the way exceptions are thrown causes Firefox and Chrome
// to be able to display the results of the system call in real-time rather
// than having to wait for the call to complete. So, I just hide the
// exception message. IE9 works with or without this.
echo "<div style=\"display:none\">";
$a = 1/0;
echo "</div>";
echo "<pre>";
system('ping -n 5 www.google.com');
echo "</pre>";
?>
To auto-scroll to the bottom of the page, I add some javascript:
<html><head>
<script language="javascript">
var int = self.setInterval("window.scrollBy(0,1000);", 200);
</script>
</head>
<body>
<?php
// insert above php code here
// stop scrolling when the execution finishes
echo '<script language="javascript">int = window.clearInterval(int);</script>';
?>
</body>
</html>
EDIT
#Chris's answer shows a much better solution.
echo '<div style="display:none">';
for ($a = 0; $a < 768; $a++)
echo ' ';
echo '</div>';

Just add this to flush the buffer:
if (eregi("chrome",$_SERVER['HTTP_USER_AGENT'])) {
echo "<div style=\"display:none\">";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo " ";
echo "</div>";
}
It has to be inside the loop. or between two output you need to show in real-time.
AND here's the shorthand trick:
add this:
if (eregi("chrome",$_SERVER['HTTP_USER_AGENT'])) {
echo "<div style=\"display:none\"></div>";
}

ob_end_flush() flushes the php output buffer, and requires an active output buffer created with ob_start().
I think you just want to call flush() to send the data to the client.
<?php
ob_implicit_flush(true);
flush();
system('ping -n 10 www.google.com');
?>

In your code, the error is pretty easy to interpret.
You call ob_end_flush() on line 3, but (like the error says), there is no output to flush. In essence, line 3 is useless because no output has been sent, so deleting the line will fix the error. If this is incorporated into a larger file, you might need to keep ob_end_flush() because some output may already have been captured.
EDIT: Since you need to flush it, either:
a: add ob_start(); to the top of the file.
b: replace ob_end_flush(); with flush();
EDIT2: Since the first didn't seem to work, this is the best I can offer: How to echo output in real time, (before script finishes)?

Related

How do I get a newline in the PHP output from echo?

I am generating a large amount of HTML code with PHP using echo and it is all appearing on one line.
I understand that HTML ignores whitespace, and there are thousands of answers which point out that you need <BR> or a block element. But that is not my question.
My problem is that is very hard to debug my HTML source code when it is all on one line. I am using Windows 7 and the Firefox browser tool Page Source to show the source code.
For a simple example, if the text editor I use shows
<HTML><BODY>
Hello, World!
</BODY></HTML>
Then the browser source code tool shows exactly that too, and when I generate it with PHP like
<?php
echo "<HTML><BODY>";
echo "Hello, World!";
echo "</BODY></HTML>";
?>
then the browser tool shows, as you would expect,
<HTML><BODY>Hello, World!</BODY></HTML>
I want to break the lines, and have tried
<?php
echo "<HTML><BODY>\n";
echo "Hello, World!\n";
echo "</BODY></HTML>\n";
?>
and with "\r\n" and with "\xA" and also like this
<?php
echo "<HTML><BODY>" . PHP_EOL;
echo "Hello, World!" . PHP_EOL;
echo "</BODY></HTML>" . PHP_EOL;
?>
yet the content stays resolutely on a single line.
This works on windows
<?php
echo "<HTML><BODY>
";
echo "Hello, World!
";
echo "</BODY></HTML>
";
?>

Can't use document.write more than one time in PHP

Here is my HTML and I call external PHP
<!DOCTYPE html>
<html>
<body>
<h1>My First Heading</h1>
<script src="index.php"></script>
<p>My first paragraph.</p>
</body>
</html>
and my PHP Script
<?
$strFileName = "poom.bis";
$objFopen = fopen($strFileName, 'r');
if ($objFopen) {
while (!feof($objFopen)) {
$file = fgets($objFopen, 4096);
// echo $file;
echo "document.writeln('$file'+);";
}
fclose($objFopen);
}
$test = "hello world";
echo "document.writeln(
'<ul>'+
'<li>.$test.</li>'+
'<li>test2</li>'+
'<li>test3</li>'+
'</ul>'
);";
?>
It error when using document.write more than one time
What should I do to solve this problem
Please Advice
PS. use echo "document.writeln('$file'+);"; for one time there is no error and show a result
First error: your line
echo "document.writeln('$file'+);";
should be
echo "document.writeln('$file');";
(without the plus sign). Also make sure that the file poom.bis doesn't contain a newline, not even at the end. If it does, you have to strip them away (trim()).
Second error was (until you edited it) the use of document.writeIn (which doesn't exist) instead of document.writeln (which does).
Tested and it works.
Also, while I'm at it, since you asked for advice how to solve this problem: look at your browser's error console and try to debug it.
echo '<script>document.writeln(';
echo '"<ul><li>test1</li><li>test2</li><li>test3</li></ul>"';
echo ');</script>';
;

PHP loop; how to print each result and delay it for a second before echoing another result?

this is my first question here on stackoverflow, I just curious.. is it possible to delay loop in PHP ? I'm trying to print each result to browser and pause the script using sleep() before it process another loop, but it's not working, here's the script that I use:
<?php
$n = 1;
while ($n < 10) {
echo $n."<br />";
$n++;
sleep(1);
}
?>
PS: I'm using Firefox and Apache2 on Linux Mint.
Servers usually buffer the output of a server side script until there's enough in it to output
try something like this. Combination of setting output buffering off and manually flushing the buffer. Note the implcit flush line and the flush and ob_flush lines.
<?php
#ini_set("output_buffering", "Off");
#ini_set('implicit_flush', 1);
#ini_set('zlib.output_compression', 0);
#ini_set('max_execution_time',1200);
header( 'Content-type: text/html; charset=utf-8' );
echo "Testing time out in seconds\n";
for ($i = 0; $i < 1150; $i++) {
echo $i." -- ";
if(sleep(1)!=0)
{
echo "sleep failed script terminating";
break;
}
flush();
ob_flush();
}
?>
PHP executes and renders its output completely before the page renders its content. So no, you can't delay the PHP loop like you want.
You could and should do this with javascript. If you need information from the server printed on delay like this, you can use AJAX to pull the information from the server as it becomes available.

How do I remove text from the console in PHP?

My goal is to print an updating progress percentage to the console (in both Linux and Windows). Currently I just print out the percentage each 10%, but I would prefer that it updated itself every 1% without filling the screen with percentages.
Is it possible to remove text you have written to the console in PHP?
echo chr(8);
will print a backspace character.
very simple
Note the example below
$removeLine = function (int $count = 1) {
foreach (range(1,$count) as $value){
echo "\r\x1b[K"; // remove this line
echo "\033[1A\033[K"; // cursor back
}
};
echo "-----------------------------\n";
echo "--------- Start -----------\n";
echo "-----------------------------\n";
sleep(2);
$removeLine(3);
echo 'hi';
sleep(2);
$removeLine();
echo 'how are you ?';
die();
See Zend_ProgressBar
PEAR's Console_ProgressBar is useful for this sort of use case.
To clear the console entirely, you can use:
if($_SERVER['SHELL']) {
print chr(27) . "[H" . chr(27) . "[2J";
}
which is quite a bit easier than keeping track of how many characters to backspace.

PHP output buffer stacking

The following is not achieving what I desire
<?
echo ob_start() . "<br>";
echo "1x<br>";
echo ob_start() . "<br>";
echo "2x<br>";
echo ob_flush() . "<br>";
echo "3x<br>";
echo ob_flush() . "<br>";
?>
The output is the following
1
1x
1
2x
1
3x
1
I am wanting something along the lines of
1x
3x
2x
I assume the problem is its putting the output from the second ob_start() in the first output buffer. But how do I get my desired output?
Basically what I am trying to achieve is providing the tag which needs to be in the head of a HTML document at a latter point in the output. Ie, half way through the script after it has already printed the docs head infomation it needs to then provide the .
Refer to the PHP manual for ob_start. You don't want to
echo ob_start();
because that function returns true or false, so it will output a 1 or 0
instead
ob_start();
echo "1x" . "<br />";
echo "2x" . "<br />";
echo "3x" . "<br />";
ob_flush();
Overall your objective isn't very clear. ob_start() is used for cleaning up a bunch of output before it is sent. It shouldn't be used as a stack.
Try SplStack if you want to use a stack in PHP.
Why don't you just write
echo "1x"."<br>";
echo "3x"."<br>";
echo "2x"."<br>";
What about the following:
<?php
echo ob_start();
echo "1x<br>";
$keep_me_1 = ob_get_contents(); /* optional and for later use */
echo ob_flush();
echo ob_start();
echo "3x<br>";
$keep_me_2 = ob_get_contents(); /* optional and for later use */
echo ob_flush();
echo ob_start();
echo "3x<br>";
$keep_me_3 = ob_get_contents(); /* optional and for later use */
echo ob_flush();
?>
If you want to use more of the "stack" functionality you should take a look at ob_end_flush.
You can use ob_get_contents() to save the contents of the inner buffer to a string, then call ob_end_clean() to throw the contents away. Later, use a callback function in the outer buffer to write out the string.
Your issue is that ob_* functions should not be echo'ed.
<?
ob_start() . "<br>";
echo "1x<br>";
ob_start() . "<br>";
echo "2x<br>";
ob_flush() . "<br>";
echo "3x<br>";
ob_flush() . "<br>";
?>
ob_start() function returns a boolean. So basically, your code is simply echoing a true value, which translates as 1 when converted to a string.

Categories