I'm trying to display the results while PHP script is running, as example.. a really long loop, i want it to echo the results while the page is loading, I searched really a lot through this and i couldn't find the good answer, After googling i found people saying use ob_flush from this question .. but it didn't work, as well as enabling the implicit_flush from php.ini , still didn't work
it only loads when the process is finished, i tried to run a for loop like this
ob_start();
for($i=0; $i<500; $i++){
echo "hm\n";
ob_flush();
}
ob_end_flush();
and still, didn't work.. it shows them all at once
My last guess now is that it needs more PHP configurations to enable/disable some stuff,
or.. it could also be apache2 configurations ?
What are the config settings that are related to this ? settings that needs to be disabled/enabled through Apache or PHP configurations ..
P.S. : I'm sure its possible to be done using PHP alone, I saw it done on GoDaddy hosting and saw it on several websites, of them http://www.checker.freeproxy.ru/checker/index.php .. if you try to submit it will show the results normally without using ajax, the website uses PHP and Apache, there's a mystery secret behind this
I used this way from this answer
while(1) {
echo "should display these lines on browser while in infinite loop.<br>";
flush();
}
or using the for loop, they both work fine, and it to make it more accurate i use ob_flush() with flush()
for($i=0; $i<5000; $i++) {
echo "should display these lines on browser while in infinite loop.<br>";
usleep(30000);
ob_flush();
flush();
}
they both work fine without ajax
Check my post here: Show progress bar in php while loop
It has some sample code as well, and covers pretty much everything you need.
PS: It can't be done with PHP alone, you need to do this with AJAX + PHP (client + server side coding). This is because the response is sent to the browser only after the file is fully interpreted.
You can't do this with PHP. PHP is run server side so it executes before the HTTP response is sent back to the browser.
You would need to use AJAX to achieve this.
You may also look at websockets to achieve this kind of thing.
You could also cheat and load all the data into a hidden list, and then use javascript to show the list items one by one after the page has loaded. :)
As mentioned above, Ajax would be the best method.
You'll need 3 files, a html file or php file that heads the job, a javascript file with your ajax in it and the php file running your script, here's an example of how you could do this. The rest is up to you if you need it tweaking for whatever you are trying to do, but it should give a sequential redout if you break up your php accordingly.
go.hml:
<html>
<head>
<title>Insert Title Here</title>
<script src="ajax_example.js" language="javascript"></script>
</head>
<body>
<form action="javascript:insert()" method="post">
<input type="text" name="limit" value="" id="limit"/>
<input type="submit" name="Submit" value="Go"/>
</form>
<div id="text_response"></div>
</body>
</html>
ajax_example.js:
// make script work for internet explorer too
function createObject(){
var request_type;
var browser = navigator.appName;
if(browser == 'Microsoft Internet Explorer'){
request_type = new ActiveXObject('Microsoft.XMLHTTP');
}else{
request_type = new XMLHttpRequest();
}
return request_type;
}
var http = createObject();
var response = '';
var current = 0;
var limit = 0;
function insert(){
current = 0;
// write to the document
response = 'Hang on...';
document.getElementById('text_response').innerHTML = response;
// set the limit and run the loop script
limit = encodeURI(document.getElementById('limit').value);
limit++;
loop_file(current);
}
function loop_file(i) {
// open the php file you wish to run, the 'hm' and 'rand' are optional, obviously
http.open('get', 'file.php?hm='+i+'&rand='+Math.random());
// run the insertReply function
http.onreadystatechange = insertReply;
http.send(null);
}
function insertReply(){
if(http.readyState == 4){
response = response+'<br />'+http.responseText;
document.getElementById('text_response').innerHTML = response;
current++;
// this runs like a pseudo for loop and will loop until it reaches the 'limit'
if(current < limit){
loop_file(current);
}else if(current == limit){
//create end script here
}
}
}
file.php
<?php
echo isset($_GET['hm']) ? $_GET['hm'] . " - hm\n" : "hm\n";
?>
Related
I am new to html and php(2hours).
I want to save the visitor geolocation data and ip address in a log file.
here is my code, i cannot pass the location data into php.
how can I do it?
I have no idea of what am i doning now.
<!DOCTYPE html>
<html>
<body>
<p id="demo">Dont click it</p>
<button onclick="getLocation()">Try It Anyway</button>
<script>
var x=document.getElementById("demo");
function getLocation()
{
if (navigator.geolocation)
{
navigator.geolocation.watchPosition(showPosition);
{enableHighAccuracy:true}
}
else{x.innerHTML="Geolocation is not supported by this browser.";}
}
function showPosition(position)
{
localStorage.loc= "Latitude: " + position.coords.latitude +
"<br>Longitude: " + position.coords.longitude;
x.innerHTML=localStorage.getItem("loc");
locOfSluts=localStorage.getItem("loc");
}
</script>
<?php
$$locofsluts = $_POST["locOfSluts"];
$contfile = fopen("NumOfSluts.log", "r");
$cont = fread($contfile,filesize("NumOfSluts.log"));
fclose($contfile );
$cont = $cont+1;
$contfile = fopen("NumOfSluts.log", "w");
fwrite($contfile , $cont);
fclose($contfile );
$log = fopen("log.log", "a") or die("Unable to open file!");
$ipOfSluts = $_SERVER["REMOTE_ADDR"]."\n";
fwrite($log, date("Y-m-d-h:i:s")."\n");
fwrite($log, $ipOfSluts);
fwrite($log, $locofsluts);
fclose($log);
?>
</body>
</html>
Since PHP is executed on the server and JavaScript is executed on the client side in your browser you cannot simply pass information from JavaScript to PHP.
The only way to archive that is to create an extra PHP script that saves the information given by some parameters and use AJAX to open an new request to this PHP file.
The problem more in detail:
You declare $loc in JavaScript and use it in PHP. It's generally not possible to use variables across multiple programming languages!!!
In this case please make sure you know the differences between PHP and JavaScript:
If you make a request to a file at the web server the PHP script starts running and generates the HTML response (so everything between is evaluated) and the output of all this will be sent to the client. Usually the connection to the server is closed afterwards.
So the PHP part of your script already ran at the server and is NOT served to the client (who wouldn't be able to run your PHP anyway since it cannot write on files at the server for example). Now your browser starts parsing the HTML result and builds the webpage for you. When the document is ready the web engine of your browser executes JavaScript and it collects the GEO information.
So when having this in mind you will see that your code cannot work for many different reasons.
The solution in detail:
You need to make an asynchronous solution for this. So you should have a .php file on your server that has no specific output. The only thing it does is saving the information given via GET parameters to your log file.
Now on your website you need a JavaScript code that fetches the GEO location data and when it succeed it should open an new connection to your .php file and pass the information you want to save as parameters to the .php script. With jQuery this would look like this:
$.ajax({
url: 'save.php?lang='+lang+'&lat='+lat,
}).done(function() {
alert('Information saved');
})
I need to list items upon search.
Instead of using some kind of loading sign, infinite progress or whatever while the serverside php script finishes it job, I would like to have the results appear as soon as they have been found serverside.
PHP side seams quite easy to perform just a fake 10x result (server.php):
header( 'Content-type: text/html; charset=utf-8' );
$i = 0;
while($i < 10)
{
?>
$('#resultZone-13').append('<div class="fileline">someresult</div>');
<?
flush();ob_flush();
usleep(200000); //0,2s
$i++;
}
clientside, I would have hoped the getScript would work, but it didn't, this is what I have:
$.post('server.php',{}, function(data)
{
},"script");
but this combination waits for the serverside script to fully complete before executing the 10 jquery commands. How can I make JQuery execute the commands as soon as they are received?
The only idea I have would be to load an offscreen iframe and ask to load the server.php page inside this iframe, but then, I'm stuck inside this iframe...
You can't, you will either have to implement socket.io or use $.getScript instead.
Try this :
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'test.php';
$('head').append(s);
Ok, I got this to work after several days off.. (Im a new dad!)
Basically this is the way to do it:
Create an invisible iframe on the document and load the remote php file in it. This php file can flush some javascript content to this iframe, this is the only way i've found to let it display it sequentially.
For instance, I got this test running:
<?
header( 'Content-type: text/html; charset=utf-8' );
echo '<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>';
$i = 0;
while($i < 10)
{
?>
<script type="text/javascript">
$(window.parent.document).find('#subfolder13').append('<div class="folderline"><div class="closedfolder" style="margin-left:48px;"></div>Pecq</div>')
</script>
<?
flush();ob_flush();
usleep(200000); //0,2s
$i++;
}
?>
I don't care about the heavy query load at the begining as this is the exact same file as the caller frame, so in 99% cases this file is freshly cached. If really needed this could be plain javascript, doesn't changes the idea behind this.
I need to force my PHP page to display the message after each round in a loop .. not at the end of loop .. as i'm running an infinite loop.
the goal is that i have a script inside a page that runs a command on the server .. takes the output and compares the data with in IF statement if it checks it displays a message .. if not .. it sleeps for three seconds and runs the loop again.
the problem is when i run the php file from a command line on the server it does exactly what it should do .. displays a message every 3 seconds (not pressing the confirmation button).. but when i run it in a browser it displays nothing (it waits for the loop to end!)
not sure if my below example will serve the purpose though.
<?php
while (1==1) {
$answer = shell_exec ("COMMAND'");
list($src, $app, $cid, $non, $flag, $dur, $exten) = explode("!", $answer);
if ($cid > 0) {
echo "<script language='javascript'>
var r=confirm('You have a call from $cid: Show Data?')
if (r==true)
{
OPEN A WEB PAGE INSIDE AN IFRAME
}
</script>";
//header( 'refresh: 15; url=monit.php' );
flush();
sleep(10);
}
else {
//header( 'refresh: 1; url=monit.php' );
sleep(1);
}
}
?>
Please note that i tried to use "header()" function to reload the page however i don't want to reload the page itself (will create a complication inside the parent page)
Any suggestions?
There are a few things to check mentioned in the manual page for the flush function:
flush() may not be able to override the buffering scheme of your web server and it has no effect on any client-side buffering in the browser
Several servers, especially on Win32, will still buffer the output from your script until it terminates before transmitting the results to the browser.
Server modules for Apache like mod_gzip may do buffering of their own that will cause flush() to not result in data being sent immediately to the client.
There are also some config file options that need to be checked mentioned in the comments
If flush() function does not work. You must set next options in php.ini like:
output_buffering = Off
;output_handler =
zlib.output_compression = Off
;zlib.output_handler =
I've also notice there are commented out lines to cause the page to refresh - you do not need to refresh the page to see the new output, the browser should show the page as still loading until the script has completed.
As has been said unless you have full control over the server this would be impossible to implement, and even if you did if you wanted to keep the connection open for a considerable length of time it would probably time out, requiring client-side continuation.
Thus, it would probably be a better idea to use AJAX, for example:
ping.php
$answer = shell_exec('COMMAND');
$r = array();
list($r['src'], $r['app'], $r['cid'], $r['non'], $r['flag'], $r['dur'], $r['exten']) = explode("!", $answer);
if($r['cid'] > 0)
$r['success'] = true;
else
$r['success'] = false;
echo json_encode($r);
Script in your public HTML/PHP file
<script type="text/javascript">
// If you're using jQuery...
var ping = function() {
$.ajax('ping.php', {
dataType: 'json',
success: function(data) {
if(data.success && confirm('You have a call from ' + data.cid + ': show data>'))
$('iframe').attr('src', 'new_page.php');
}
});
};
setInterval(ping, 3000);
</script>
Drop this into your htaccess (turns of gzip):
SetEnv no-gzip dont-vary
and to echo the message and flush output buffer do this in your loop:
echo $msg;
ob_flush();
flush();
I am trying to get data instantly with ajax, but I couldn't. The problem is, when I make a request, response is coming end of the php process. I want to get data after every echo command. So here is the simple example. There is two files, main html file (included javascript) and php file.
try.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Get Data</title>
<script type="text/javascript">
function makeObject() {
var newObject;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer"){
newObject = new ActiveXObject("Microsoft.XMLHTTP");
}
else {
newObject = new XMLHttpRequest();
}
if (newObject.overrideMimeType) {
newObject.overrideMimeType('text/xml; charset=UTF-8;');
}
return newObject;
}
var newOne=makeObject();
function getData()
{
newOne.open('get','process.php',true);
newOne.onreadystatechange=function(){
if (newOne.readyState==4)
{
var box=document.getElementById("queryResult");
box.innerHTML=newOne.responseText;
}
}
newOne.send(null);
}
</script>
</head>
<body>
<input type="button" id="doit" value="Start Query" onclick="getData();" />
<div id="queryResult"></div>
</body>
</html>
and process.php
<?php
echo "1";
sleep(1);
echo "2";
sleep(1);
echo "3";
sleep(1);
echo "4";
sleep(1);
echo "5";
?>
when I click the Start Query button, it is waiting 4 seconds and then write 12345 at the same time. I want to write 1 and wait 1 sec then write 2 and wait 1 sec then write 3 etc. How can I do that? Sorry for my English, thanks for the answers :)
ajax waits for a response, so you are making the final response wait. you would have to do seperate requests. Possibly set subsequent request of dependant upon the result of the previous one(s).
You need to use an html5 web socket. Using standard ajax will not return until the request has completed.
your code is doing exactly what you ask. The ajax response is supplied to you on the client side when the last byte is received not as it is received.
if you are after progress from the server side to appear on the client side then the client must poll and the server maintain a some state to respond, not as you have it with the server trying to send a stream response. The new HTML5 client side sockets may help you here where rather than polling the client can be called by the server
If I understand your question you will need to make 4 ajax method calls. Since you are expecting different values from each call you need to have the state saved somewhere (on client or server) so that you know which call you are on. If the pauses in your sample are part of your intended program (and not just for the sake of the sample) then it would probably be better in your client-side Javascript.
Servers buffer their output - sending a single character is extraordinarly wasteful of network resources. To force PHP and the webserver to flush their buffers, you need at least:
echo "1";
flush();
ob_flush();
echo "2";
etc...
I was wondering how to make progress bar like gmail.
I tried
<script src="jquery.js"></script>
<script>
$(function (){
$.ajax({
url: 'index.php',
success: function(data) {
$('#bar').html(data);
}
});
})
</script>
<div id="bar"></div>
And on index.php
[EDIT]: by sleep() i just meant to simulate continuous stream of output like multithreaded programs which is not supported in php.
<?php
for($i=0; $i<=10; $i++)
{
sleep(1);
echo "$i";
}
it seems that output is echoed out at once so i get result 012345678910 at once.
also i tried
setInterval(function (){
$.ajax({
url: 'index.php',
success: function(data) {
$('#bar').html(data);
}
});
}, 1000);
Instead, i had trouble maintaining value of 'progress', so i did
<?php
session_start();
if(isset($_SESSION['value'])){
if($_SESSION['value'] >= 10)
{
unset($_SESSION['value']);
}
else
{
$_SESSION['value']++;
}
}
else
{
$_SESSION['value'] = 0;
}
echo $_SESSION['value'];
as part of my php. But it seems that, i am calling ajax function on continuous interval.
My Question is,
How does google use progress bar, while loginng in gmail. Do they get continuos 'stream' of data like i tried on my first example or send (regularly) request on some url (though not through ajax .. through JSONP or whatever) and upadate the page like second ?
Can I do same with php , even if not with php, can I do it using javascript and other server side scripting language where multithreading is supported?
I'm not sure what exactly Gmail does for the progressbar, but you can achieve something similar in PHP, although it may be a bit tricky.
First, to explain why your examples don't work:
If you echo and sleep, like your first example, it will never work. Ajax performs a full request - that is, if the response does not finish, it will wait. When you loop and sleep, the request is not "closed" until the PHP script has finished executing.
If you use session, like in the other example, the problem becomes the session store. The store is typically locked during script execution, and it will not update itself to allow for the type of progress check you want.
What you could do is write progress to a file (or to a database) manually. For example:
file_put_contents('progress.txt', 1);
Then, have another script read the file and output the contents.
This should work, because file_put_contents opens, writes and closes the file.
Using some other language than PHP would make it easier. Being multithreaded would possibly make it easier, but is not a requirement. However, having a continuously running process would make it simpler (PHP only runs a process for the duration of your request and then exits)
run your jquery code at an interval, and use PHP to print the progress percenage and draw the bar then.
so it will be something like
<script>
function bar()
{
var v=getProgress(...);
setTimeout("bar()",1000);
drawBar();
}
function drawBar(l)
{
//set div's length to l
}
</script>
EDIT 2
<?php
/* get the request and calculate the job completion percentage and echo it ! */
?>
I think Gmail shows progress when it loads all resources, like JS files. There are different ways to do this: you could dynamically include all resources with JS, or you could make all included JS files report that they've been loaded.
To make PHP output partial output, use this:
ob.php
<?php
ob_start();
for ($i = 0; $i < 100; $i++) {
echo "{$i}<br />";
ob_flush();
flush();
usleep(100000);
}
.htaccess
php_value output_buffering "0"
this thread and this link helped me to find out solution for the same problem, so i am providing it for the record:
test.php:
<?php
for($i=0; $i<100; $i++)
{ usleep(100000); //100ms
echo 'A'; ob_flush(); flush();
}
?>
test.html:
<body>
<button onclick='call()'>call</button>
<div id='progress'>...</div>
<script>
function fprogress(e)
{ document.getElementById('progress').innerHTML ='progress: '+e.loaded +'%'; }
function call()
{ var req = new XMLHttpRequest();
req.addEventListener("progress", fprogress, false);
req.open('GET', 'test.php', true); req.send(null);
}
</script>
</body>
... so test.php can be any JOB which doing some stuff... and while doing it ECHOes 100 characters (bytes) with flashing buffer.
As per my opinion, you can divide your login process in several parts and checks.
Every part check completed send response to your progress bar and progress bar width will increase such patterns. After that progress bar will send next request to your login process for step untill you will not get upto 100% login and redirect.