I'm trying to show function status as its looping but delete the previous status before the next one shows. Current code:
<?php
#ini_set('zlib.output_compression',0);
#ini_set('implicit_flush',1);
#ob_end_clean();
set_time_limit(0);
// Perform 1st function here
echo "Retrieving Data...";
echo str_repeat(' ',1024*64);
sleep(1);
// Perform 2nd function here
echo "Analyzing Data...";
echo str_repeat(' ',1024*64);
sleep(1);
// Perform 3rd function here
echo "Done...";
echo str_repeat(' ',1024*64);
sleep(1);
// Clean all echos here..
?>
<html>
<head>
// Dynamic head content as a result of the php functions above
</head>
<body>
</body>
</head>
Now this works, but displays all the echos one after the other. I'd like the next status to replace the first, until the end, then remove "Done" before the html is displayed.
I tried:
ob_start();
echo "Retrieving Data...";
echo str_repeat(' ',1024*64);
sleep(1);
ob_end_clean();
But that didn't work. Is this possible at all?
The following uses the last-of-type pseudo CSS selector to hide all the old progress status messages. It's a reasonably new selector so it doesn't work well on older browsers (pre IE9), you can check the compatibility on the Mozilla Developer Network
<html>
<head>
<style type="text/css">
#progress span {
display: none;
}
#progress span:last-of-type {
display: block; !important
}
</style>
</head>
<body>
<div id="progress">
<?php
for ($i =0; $i<=100; $i+=10) {
ob_start();
echo "<span>$i%</span>";
ob_end_clean();
sleep(1);
}
?>
</div>
</body>
</html>
Output your lines with a \r. This will return the cursor to 0 on the same line. Where you can write over it.
echo "Retrieving Data..\r";
sleep(3);
echo "Analyzing Data...\r";
sleep(3);
echo "Done... \r\n";
I added a \n to the last echo otherwise the command prompt would over write the last echo.
Related
I am using simple-html-dom for my work. I want to get all PHP script (<?php ... ?>) form file using simple-html-dom.
if i have one file (name: text.php) with below code :
<html>
<head>
<title>Title</title>
</head>
<body>
<?php echo "This is test Text"; ?>
</body>
</html>
then how can i get this PHP script <?php echo "This is test Text"; ?> form above file of code using simple-html-dom.
$html = file_get_html('text.php');
foreach($html->find('<?php') as $element) {
//Sonthing code ...
}
i can not use like this, Is there any other option for this ?
Here's a solution using regex. Note that regex often is not advisable for parsing HTML files. That is, it might be okay in this case.
This will match each instance of a PHP code block and allow you to output (or do whatever else you want) either the entire block (including the tags) or the code that is contained within the block. See the documentation for preg_match_all().
<?php
$string = <<<'NOW'
<html>
<head>
<title>Title</title>
<?php echo "something else"; ?>
</head>
<body>
<?php echo "This is test Text"; ?>
</body>
</html>
NOW;
preg_match_all("/\<\?php (.*) \?\>/", $string, $matches);
foreach($matches[0] as $index => $phpBlock)
{
echo "Full block: " . $phpBlock;
echo "\n\n";
echo "Command: " . $matches[1][$index];
echo "\n\n";
}
DEMO
I am using Codeigniter and want to show progress of XML import.
but issue i am facing is
When view load, it stuck on loading (blank page) and when i can see view its shows 100% done.
my code as bellow
$i=0;
$count=sizeof($record->List);
foreach($record->List as $Item)
{
$i++;
echo "processing ".$i." of ".$count;
---processing code which takes times to process---
---processing code which takes times to process---
}
this code is in view but when i click on link to load this view, i have to wait for all process to complete and then i can see view when all process is done.
what i want is:
Show view (empty).
Then keep on printing each line as loop go.
Thanks
Here you got a example for progress bar using AJAX:
index.php
<?php
// Start the session.
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<title>Progress Bar</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<style>
#progress {
width: 500px;
border: 1px solid #aaa;
height: 20px;
}
#progress .bar {
background-color: #ccc;
height: 20px;
}
</style>
</head>
<body>
<div id="progress"></div>
<div id="message"></div>
<script>
var timer;
// The function to refresh the progress bar.
function refreshProgress() {
// We use Ajax again to check the progress by calling the checker script.
// Also pass the session id to read the file because the file which storing the progress is placed in a file per session.
// If the call was success, display the progress bar.
$.ajax({
url: "checker.php?file=<?php echo session_id() ?>",
success:function(data){
$("#progress").html('<div class="bar" style="width:' + data.percent + '%"></div>');
$("#message").html(data.message);
// If the process is completed, we should stop the checking process.
if (data.percent == 100) {
window.clearInterval(timer);
timer = window.setInterval(completed, 1000);
}
}
});
}
function completed() {
$("#message").html("Completed");
window.clearInterval(timer);
}
// When the document is ready
$(document).ready(function(){
// Trigger the process in web server.
$.ajax({url: "process.php"});
// Refresh the progress bar every 1 second.
timer = window.setInterval(refreshProgress, 1000);
});
</script>
</body>
</html>
checker.php
<?php
// The file has JSON type.
header('Content-Type: application/json');
// Prepare the file name from the query string.
// Don't use session_start here. Otherwise this file will be only executed after the process.php execution is done.
$file = str_replace(".", "", $_GET['file']);
$file = "tmp/" . $file . ".txt";
// Make sure the file is exist.
if (file_exists($file)) {
// Get the content and echo it.
$text = file_get_contents($file);
echo $text;
// Convert to JSON to read the status.
$obj = json_decode($text);
// If the process is finished, delete the file.
if ($obj->percent == 100) {
unlink($file);
}
} else {
echo json_encode(array("percent" => null, "message" => null));
}
process.php
<?php
// Start the session.
session_start();
// The example total processes.
$total = 20;
// The array for storing the progress.
$arr_content = array();
// Loop through process
for ($i = 1; $i <= $total; $i++) {
// Calculate the percentation
$percent = intval($i / $total * 100);
// Put the progress percentage and message to array.
$arr_content['percent'] = $percent;
$arr_content['message'] = $i . " row(s) processed.";
// Write the progress into file and serialize the PHP array into JSON format.
// The file name is the session id.
file_put_contents("tmp/" . session_id() . ".txt", json_encode($arr_content));
// Sleep one second so we can see the delay
sleep(1);
}
Just that you write it on the CI and create a tmp folder, and you point a path to it in script. Good luck!
I am just a amateur php programmer!
I have a specific requirement.
I want to control php output behaviour in my script.
What i want is this thing
myscript.php
echo "phase 1";// (output to browser immediately)
echo "Proceeding further....";
sleep (10);
echo "phase 2";// (output to the browser immediately)
sleep(10);
echo "phase end";
But what happens is all the output of echo gets dump after 20 second i mean complete output not sequencewise...
How can i output it in sequence wise.. i do not know what it is called ! Please also show a example if possible it helps in understanding
You might wanna take a look at some Websocket like Rachet. For a simpler version, you just use a combination of Javascript/Ajax and PHP.
EDIT: The simplest way; the jQuery/PHP way
As requested in the comments, this is a very simple, insecure way of achieving asynchronous server work/feedback.
Server-side
//doTheWork.php
switch($_POST['step'])
{
case 1:
$output = shell_exec('cat text.txt'); //Do whatever you need to do here
break;
case 2:
$output = shell_exec('ls');
break;
default:
$output = "No or invalid step declared";
}
echo $output;
Client-side
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testing live feedback</title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script> <!-- Include your local version of jQuery -->
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
</head>
<body>
<div id="console">
<h2>Output from server</h2>
<div id="console_output">
</div>
</div>
<script type="text/javascript">
var totalSteps = 5;
var currentStep = 0;
var url_to_server = "http://localhost/doTheWork.php";
function executeAndOutputData()
{
currentStep++;
if(currentStep >= totalSteps) return;
$.post(url_to_server, {step:currentStep}, function(response){
$("#console_output").append(response+"<br>");
executeAndOutputData();
});
}
executeAndOutputData();
</script>
</body>
</html>
Yes you can natively with PHP using flush functions.
Example with your code :
<?
echo "phase 1";// (output to browser immediately)
echo "Proceeding further....";
flush();
ob_implicit_flush(true);
ob_flush();
sleep (10);
echo "phase 2";// (output to the browser immediately)
sleep(10);
echo "phase end";
?>
edit : But, this is just to answer you. A such code is certainly fully useless and must be improved to remove sleep calls.
I am satisfied with Dencker answer but still i now know a simpler way by using only PHP.
Derived from http://www.codeproject.com/Tips/680085/Real-time-Updating-of-PHP-Output
// Turn off output buffering
ini_set('output_buffering', 'off');
// Turn off PHP output compression
ini_set('zlib.output_compression', false);
//Flush (send) the output buffer and turn off output buffering
while (#ob_end_flush());
// Implicitly flush the buffer(s)
ini_set('implicit_flush', true);
ob_implicit_flush(true);
echo "Start<br />";
echo str_pad("",1024," ");
echo "<br />";
ob_flush();
flush();
sleep(5);
echo "Program Output";
ob_flush();
flush();
And it does work without any server config and it is well suited for my need (temp). But i will be looking at the suggestion posted here.
Could someone please save these 2 files and run them and tell me why I get the error " ob_flush() [ref.outcontrol]: failed to flush buffer. No buffer to flush". I tried googling around and it says that I have to use ob_start(); but when I do then it doesn't print out line by line, but rather returns the whole object from the FOR loop when it has completed. I'm kinda new to PHP so I'm not sure where else to look..
test_process.php
// This script will write numbers from 1 to 100 into file
// And sends continuously info to user
$fp = fopen( '/tmp/output.txt', 'w') or die('Failed to open');
set_time_limit( 120);
ignore_user_abort(true);
for( $i = 0; $i < 100; $i++){
echo "<script type=\"text/javascript\">parent.document.getElementById( 'foo').innerHTML += 'Line $i<br />';</script>";
echo str_repeat( ' ', 2048);
flush();
ob_flush();
sleep(1);
fwrite( $fp, "$i\n");
}
fclose( $fp);
main.html
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css" media="screen">
.msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
.new{ background-color:#3B9957;}
.error{ background-color:#992E36;}
</style>
</head>
<body>
<iframe id="loadarea" width="1024px" height="768px"></iframe><br />
<script>
function helper() {
document.getElementById('loadarea').src = 'test_process.php';
}
function kill() {
document.getElementById('loadarea').src = '';
}
</script>
<input type="button" onclick="helper()" value="Start">
<input type="button" onclick="kill()" value="Stop">
<div id="foo"></div>
</body>
</html>
You only need ob_flush() if an output buffer is active (for example by ob_start(), or by configuration settings). If you haven't, just remove the ob_flush(). Or you can make it conditional:
if (ob_get_level() > 0) {ob_flush();}
I think you are confusing ob_flush() with flush(). While ob_start() and ob_flush() handles a PHP internal output buffer that catches all outputs, flush() is the normal function that flushes STDOUT like in other programming languages.
Example:
<?php
ob_start();
echo "Foobar\nFoobar\nFoobar\n";
// Nothing printed yet
ob_flush(); // Now it is printed.
echo "Foobar\n"; // Printed directly, because contains a line ending.
echo "Foobar"; // Not printed, because normally buffers are flushed on line endings
flush(); // Printed.
EDIT:
Your output is not printed, because your webserver may buffer the contents. Try to turn off compression and output buffering:
#apache_setenv('no-gzip', 1);
#ini_set('zlib.output_compression', 0);
#ini_set('implicit_flush', 1);
Please also keep in mind, that Safari and Internet Explorer have an internal 1K buffer. So you need to add 1 KB of padding data (like spaces), to make them render.
EDIT 2:
Your implementation is broken. You want to poll your data with ajax. Use jQuery on the client side:
<div id="counter">0%</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
<script type="text/javascript">
function doPoll(){
$.post('script-that-returns-stuff.php', function(data) {
$("#counter").html(data);
setTimeout(doPoll,5000);
});
}
doPoll();
</script>
Then in script-that-returns-stuff.php:
<?php
$file = explode("\n", file_get_contents("/tmp/output.txt"));
$last_line = $file[count($file)-1];
echo $last_line."%";
Where is ob_start()?
ob_flush flushes the output buffer to your file handle. Maybe you have it wrong.
An example:
ob_start(); //start output buffering
echo 'hello world'; //not outputed
ob_flush(); //sends the output buffer so displays hello world.
manual
On this page http://www.effectivewebsolutions.biz/video-spokesmodel.html if you put in your URL it opens it through fopen function and puts a video spokes-model on the website for demonstration purposes, here is the script.
<?php
$handle = fopen($_POST["url"], "r");
while($data = fread($handle, 1000000)){
$contents .= $data;
}
fclose($handle);
echo "<base href=\"{$_POST['url']}\">";
echo "\n\n";
echo "<!-- Begin inserted page -->";
echo "\n";
echo $contents;
echo "\n";
echo "<!-- End inserted page -->";
echo "\n\n";
echo '<script type="text/javascript" src="http://www.internet-spokesmodels.com/scripts/swfobject.js"></script>';
echo '<style type="text/css" media="screen">object { outline:none; } </style>';
echo "\n";
echo '<script type="text/javascript" src="http://www.internet-spokesmodels.com/actors/script/SabrinaEXAMPLESredshirt_350x500.js"></script>';
?>
However in Safari it only opens text version of the website (no css or images).
It doesn’t make sense why would browser make a difference in this case.
Any Ideas?
Probably because the page does not render valid HTML. When I tried it with http://www.google.ca, I got:
<base href="http://google.ca">
<!-- Begin inserted page -->
<!doctype html><html><head><meta http-equiv="content-type" ...
The DOCTYPE should be the first thing in the page, followed by a <html> tag with HTML content. The <base> tag should be within the <head> tag.
You can't blame Safari for displaying invalid HTML incorrectly.
The HTML code being returned should be identical across browsers, since browsers have nothing to do with server-side code. Check the validity of HTML. Also, sanitize your input as suggested meagar.