There is a buffer in the built-in webbrowser of ZZEE PHPExe. Currently you
can not do anything about it, because on PHP side when you do flush() it
sends data immediately to the built-in browser, but the latter buffers
data.
This is in the todo list.
Perhaps you can change your application a little bit to avoid relying on
flush().
Paul.
Or try a Flash progress bar.
You do this sort of thing client-side, not server-side. Javascript,
flash, AJAX, etc. - all of these techniques will work. You could even
just put one box inside another, with different background colors, and
then change the width in the inner one.
The client/server model inherent in web apps doesn't really have a way
of letting the client know the progress of the server. The server is
supposed to be kinda instant.
There are ways you could work around it. You could have the
client-side Javascript tick away a little timer function, make a fresh
"How are things going?" HTTP request on each tick, and update some
property of the GUI depending on the reply.
Generally speaking though, the rule is, only client-side code gets to
update the GUI. (The distinction may seem strange in PHPExe, where you
only have one machine, but it is still there).
The distinction is simple: client side is Javascript, server side is PHP
:)
> Thanks for your answer, my only problem is, I need to update the
> progress
> while in a php foreach() loop :-(
> And that doesn't seem to be possible with PHPexe....
> I'm querying a mysql-db, fetch files over ftp and execute them via
> exec(),
> all within a foreach() loop.
You can move it to Javascript: get a mysql-db query via PHP, results via
AJAX / JSON to Javascript, then do a loop in Javascript, then call a PHP
script via AJAX to run exec(), then update your UI via Javascript.
> By the way I'm not skilled enough in AJAX or FLASH to launch that kind
> of a
> campaign....
AJAX is a trivial thing, you can learn it a couple of minutes. There are
lots of frameworks as well.
This flush() support is in the todo list and we will try to fix it.
php -q <filename.php>
and then you'll get all your printfs coming out on the command prompt
window right away.
Just a thought.
The new version 2.4 has an experimental support for "no buffering" mode.
To turn it on, do this Javascript code first:
external.buffering = false;
Please test and let me know if it works for you.
If you want to turn the buffering back on, do:
external.buffering = true;
Hmm... in our tests it worked as in Apache. Maybe I was not clear enough.
You need to do
external.buffering = false;
*before* a PHP script you want to update a progress bar is launched.
For example, the first screen is a kind of entry, a main form, and the
second one does some lengthy job, during which you want to keep your user
updated. So in this example, you need to set external.buffering to false
on the first screen, so before the second screen runs this flag has
already been set. That is, the first screen needs to have
<script type="text/javascript">
external.buffering = false;
</script>
If you still can't make it work, can you make a simple example that
illustrates your problem and send its source code over to support at zzee
dot com?
The following example works for me fine (basically I replaced ftp stuff
with sleep() in your example). What is your OS and webbrowser?
========================================
<div id="status">abc</div>
<?php
$x = array('file1', 'file2' , 'file3');
foreach($x as $file) {
print "<script>document.getElementById('status').innerHTML='Loading File
$file'</script>\n";
flush();
sleep(3);
}
echo
"<script>document.getElementById('status').innerHTML='Done';</script>";
?>
I recommend that you use more correct syntax, in particular, add
type=\"text/javascript\" into the <script> tag, like in the example below.
Try to compile my example, does it work for you?
=======================================================================
<div id="status">abc</div>
<?php
$x = array('http://www.google.com', 'http://www.yahoo.com' ,
'http://www.cnn.com');
foreach($x as $file) {
echo "<script
type=\"text/javascript\">document.getElementById('status').innerHTML='Getting
$file';</script>\n";
@flush();
sleep(3);
//file_get_contents($file);
}
echo "<script
type=\"text/javascript\">document.getElementById('status').innerHTML='Done';</script>";
?>
http://www.zzee.com/phpexe/flush.zip
It works OK on all test computers.
In short, I recommend that you use both flush() and ob_flush() to update
the screen. Below is these two files:
index.php
=======================================
<html>
<head>
</head>
<body>
<script type="text/javascript">
// This is what needs to turn ZPE into a non buffering mode
external.buffering = false;
</script>
<h2>Flush() Test</h2>
<form action="buffering.php" method="post">
URLs to download:
<br/><textarea name="files" style="width: 90%; height:
200px;">http://google.com
http://yahoo.com
http://microsoft.com
http://facebook.com
http://en.wikipedia.org
</textarea>
<br/><input type="checkbox" name="doActualFile" value="1"
checked="checked"/>
Download URLs? (otherwise just sleep() is called)
<br/><input type="submit" value="Go" />
</form>
</body>
</html>
=======================================
buffering.php
=======================================
<?php
$getActualFile = isset($_REQUEST['doActualFile']) ?
($_REQUEST['doActualFile'] + 0) : 0;
$files = $_REQUEST['files'];
$files = preg_split('/\r?\n/', $files);
?>
<div id="status">Progress information...</div>
<script type="text/javascript">
var s = document.getElementById("status");
function updateStatus(text) {
s.innerHTML = text;
}
</script>
<?php
foreach($files as $file) {
if ($file == '') { continue; }
showProgressInfo("Getting " . $file);
if ($getActualFile) {
@file_get_contents($file);
} else {
sleep(3);
}
}
showProgressInfo("Done");
// After you are done with the progress it is better to turn the buffering
mode on:
echo <<<ABCDEF
<script type="text/javascript">
external.buffering = true;
</script>
ABCDEF;
function showProgressInfo($text)
{
echo "<script
type=\"text/javascript\">updateStatus(\"$text\");</script>\n";
// Just in case we send 256 bytes of output
// If no updating happens, uncomment this block
/*for ($i = 0; $i < 32; $i++) {
echo "<!-- -->";
}*/
// Do both flush and ob_flush
@flush();
@ob_flush();
}
?>
=======================================
I recommend that you use both flush() and ob_flush(), please see my
example. Compile the example on your computer and let me know.
If anyone has problems with the sample, please let me know.
Have you been able to make it work? Have you compiled my sample?
> we used a different approach by using a JS-Loop and call the php-script
> within the loop
You need to put
<script type="text/javascript">
external.buffering = false;
</script>
one step earlier, before this script with a JS loop runs, i.e. this
javascript code should have been executed in the previous URL.
> we were not able to get your example working.....no screenupdates over
> the
> runtime of the script, just the last value when the script is exiting
> :-(
Have you compiled the example intact? Please confirn whether this example
works for you if compiled intact. Also you can replace there http: URLs
there by ftp: to see how ftp works as well (right in the textarea box on
the first page).