Output buffer based progress bar - php

I have been trying to get the following code working.
It's a progress bar trick which uses ob_get_clean() function.
Don't know why but this script just don't work!
Only the initial percent - 1% comes up and nothing after that.
<?php
error_reporting(8191);
function flush_buffers(){
#ob_end_flush();
#ob_flush();
#flush();
#ob_start();
}
$ini = 2;
echo '<script>document.getElementById(\'lpt\').style.width=\'1%\';</script><br>';
for($i=1;$i<=100;$i++) {
$k=$ini-1;
$str=str_replace("width=\'$k%\'","width=\'$i%\'",ob_get_clean());
$ini++;
echo $str;
flush_buffers();
}
?>

You can't 'retract' output text after you've sent it to the client. It merely gets appended.

It would not work as you are trying to mix server and client side code. PHP Code on the client side would not work. You will need to build the whole progress bar using javascript itself.

What #Delan says: You can't "take back" and edit output that has already been sent to the client. You would have to output a completely new <script> snippet for every movement of the percentage bar.

You can't do progress bar in PHP, you must write in eg. JavaScript, and only echo with PHP.
You can't do that because PHP is server-side language and any loading is performing on client-side because server don't loads anything then loading script you must have in client-side language.

i don't think any of these answers are complete or correct that are up-voted.
it's true that you can't retract output, but you CAN do what KPL wants to do using a simplistic non-ajax approach that doesn't even require javascript... i do this all the time. tested on ie 9, firefox, chrome and safari. perhaps it could be true that in 2010 when this was asked this technique didn't work, but i don't see why now. it's not html5 or anything fancy...
you do so using ob_flush like KPL guesses and you re-output the current bar html (however you like it to look, fancy/animated/etc) with position:absolute and an incrementing z-index:$counter. that way on each loop the output gets flushed as the php is running on the server and the new output is neatly placed over top of the previous output. sounds messy, but this technique looks perfect and works really really well on every browser i've tried.

Related

Is it bad practice to dynamically change a value with an infinite while loop?

I'd like a section of text that is already dynamically changing every 10 minutes to do it without refreshing the page. I was thinking something along the lines of:
<?php
while (1 < 2) {
echo $value;
sleep(60);
}
?>
I realize that's a dumb way to make a while loop run and I would think it would work with just "while(){}" but I just wanted to make sure, that will be corrected when I actually write this thing as long as this isn't terrible to do. If there is a better way I'd love to hear it! thanks!
Edit: I just noticed it would echo the value after the first, any cleaver ways to make it replace it?
Edit2 Here's the php function I already written to retrieve the changing value:
<?php
function getTotal($basePrice){
$dogeValue = file_get_contents("https://www.dogeapi.com/wow/?a=get_current_price");
$postage = .49/$dogeValue;
return round($sellAmount = $basePrice/$dogeValue - $postage - ($basePrice*0.1/$dogeValue));
}
?>
The short answer: yes, that is bad practice.
Reasons include:
You tie up your server (will probably time out)
Unless you play around with the buffering, things will not be reflected at the time you want
You never send the close tag to the browser (or anything else that happens later).
It is tricky to overwrite what was already there, so you end up with the output increasing instead of changing.
Recommendation:
Use client side code (javascript, AJAX) - don't try to do this server side.
You can see an example of periodic AJAX at https://stackoverflow.com/a/6378771/1967396 .
For periodic JavaScript, see many good answers at Is there any way to call a function periodically in JavaScript?
This script will never show you anything, because until processing the php script is not done, web server doesn't send anything to output, considering your infinite loop, it will never happen.
instead of this not-working idea, use Ajax, cron jobs, or even pure javascript, its very simple and more rational certainly.

setInterval doesn't seem to re-execute php script

what i'm trying to do is get a variable to update every 5 seconds doing this:
setInterval(document.getElementById("listeners").innerHTML =
"<?php include('../includes/shoutcaststuff.php');
echo $dnas_data['CURRENTLISTENERS']; ?>",5000);
but what happens is the inner html is set but doesn't update every 5 seconds like it should.
my guess is that the php only executes once, but i have no idea if that's the case or not.
and i'm aware i should make a function to do the stuff inside setInterval... i'll clean up the code once i figure out how to make it work.
thanks in advance.
ok... ajax was 'the best' answer since no more than 2 people would be logged in at a time here so server requests isn't such a big deal.
here's how i got it to work:
function lCount(){
$.get("../includes/shoutcaststuff.php",{Count: "TRUE"}, function(data){
document.getElementById('listeners').innerHTML = data;
});
}
setInterval(lCount,5000);
and added this to the end of the php:
if(isset($_GET["Count"])){
echo $dnas_data['CURRENTLISTENERS'];
}
now it works fine.
thanks for the suggestions guys :)
<?php include('../includes/shoutcaststuff.php');
echo $dnas_data['CURRENTLISTENERS']; ?>
This code only executes once when the page is built. For the rest of the times this javascript is called whatever is first echoed will be the value.
Instead of using a static value here, you are going to need to use an ajax request (or a websocket if you want to use html5). The request will then hit your server once every 5 seconds. Keep in mind that this can cause undue load on your server.
Ratchet is a commonly used PHP WebSocket implementation that allows for data to be sent to the client using push technology. This is probably more preferable than using your polling approach.
PHP code is run on the server generating the HTML/JS. Use ajax if you need to run php code once the page has loaded.
Take a look at this for example;
Using this:
setInterval(document.getElementById("listeners").innerHTML =
"<?php echo "1";?>",5000);
Will output this to the browser:
setInterval(document.getElementById("listeners").innerHTML =
"1",5000);

does a PHP page with includes get compiled and sent as one page?

I have a PHP page where the header and footer are PHP includes.
I want to know if there is any possibility of the includes loading asynchronously - or does PHP gather all the files required, compile them and send them as one file?
The reason I ask is that I've seen an interesting PHP app that seemed to keep the connection open and do things in sequence before closing the connection - I wondered if that's what happens with includes.
PHP version is 5.3.6
EDIT:
What I actually want is for the page to load all at once, to prevent my layout mashing as each bit loads. Sorry to any who misunderstood this
PHP does gather and compile them; everything goes to the browser as a single document. If you don't want this, you'll have to do something with XMLHTTPRequest on the frontend
Generally any output will be output as it is generated.
echo 'A';
sleep(1000);
echo 'B';
sleep(1000);
echo 'C';
This slowly outputs "ABC". Includes are included when they are encountered, the same way echo outputs anything at that specific point. It's all in order, never asynchronously.
A web server may buffer all output before sending any of it to the client. In the above example, you'd receive "ABC" all together after 2 seconds of nothing.
If your objective is to receive all the page at once you need to use ob_start() and ob_end_flush(). Do something like:
ob_start();
...
write all your outputs
...
ob_end_flush();
This will force the server to buffer the output until the whole page is prepared.
Good luck!
I use the following architecture when loading a page on my application:
index.php
<script src="path/to/js/lib/jslib.js" type="text/javascript"></script>
window.addEvent('load', function()
{
BuildPg(PgStatus); //PgStatus is a variable I use in a state machine to build different pages
});
<form>
<div id="DivPgTop"></div>
<div id="DivPgMiddle"></div>
<div id="DivPgBottom"></div>
</form>
This is the entire index.php
In my jslib.js I have functions like:
function BuildPg(Pg) {
BuildPgTop(Pg);
BuildPgMiddle(Pg);
BuildPgBottom(Pg);
}
function BuildPgTop(Pg) {
var Content="";
if (Pg == 1) {
Content = function_a(); // function_a builds the top of the page
else if (Pg == 2) {
Content = function_b();
etc...
}
document.getElementById("DivPgTop").innerHTML = Content; //here is where I load the top of the page
}
And I do the same for the other parts of the page Middle and Bottom.
Using this framework, if you changed my BuildPg() function to something like:
function BuildPg(Pg) {
BuildPgTop(Pg);
sleep(foo);
BuildPgMiddle(Pg);
sleep(bar);
BuildPgBottom(Pg);
}
Your user would experience the top of the page loading first, a delay, the middle of the page, another delay, and the bottom.
And if you change the order of the function calls you could even have the bottom of the page load first, then the middle and the top.
I hope this makes sense. Good luck!
PHP sends a single document. What you want to do is achieved with something called AJAX (http://en.wikipedia.org/wiki/Ajax_%28programming%29)
Basically you write some JavaScript code that uses XMLHTTPRequest object to connect to the server and download some extra info.

Can't send content-type: text/xml header from PHP at the same time getting the data from MYSQL

i hope you can cast some light on my problem. I need to do an AJAX / PHP / MYSQL application to display posts and stuff on the page i'm writing.
I only discovered how to do some simple stuff in PHP after taking some mushrooms but that was years ago and now i don't have mushrooms and i'm just stuck!
So here's the problem:
i think i need to send a proper "xml" file through php so the ajax part can take it but: when i try to put the header on top of the php it displays this error:
" Extra content at the end of the document "
When i looked at some tutorials people were using the "header" fearlesly to do such stuff as i want to do and no comments suggested that it didn't work. so why it doesn't work on my local server?
I'm running:
WAMP
Apache 2.2.11
PHP 5.3.0
It also doesn't work on a remote server (PHP 5.3.0) :/
I read all the stuff i could find till 5am and decided to ask you for help for the first time :)
Thank you!
header('content-type: application/xhtml+xml; charset=utf-8');
require_once("allyouneed.php");
require_once("bazingablob.php");
$category=$_GET["category"];
$post_tags=$_GET["post_tags"];
$language=$_GET["language"];
$author=$_GET["author"];
$posts_per_page=$_GET["posts_per_page"];
$current_page=$_GET["current_page"];
$order=$_GET["order"];
$hard_limit=$_GET["hard_limit"];
$show_hidden=$_GET["show_hidden"];*/
$wypluj="";
$wypluj="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
$bazinga_blob = new bazingablob;
if (!$bazinga_blob->connect_to_database())
{
$wypluj.="<IsOK>0</IsOK>";
echo $wypluj;
exit;
}
else
{
$wypluj.="<IsOK>jedziem</IsOK>";
}
$bb_result=$bazinga_blob->get_all_posts($category,$post_tags,$language,$author,$posts_per_page,$current_page,$order,$hard_limit,$show_hidden);
if ($bb_result) //udalo sie cos znalezc w bazie wedlug kryteriow
{
$wypluj.="<Pagination>";
$wypluj.="<CurrentPage>";
$wypluj.=$bazinga_blob->posts_pagination["current_page"];
$wypluj.="</CurrentPage>";
$wypluj.="<LastPage>";
$wypluj.=$bazinga_blob->posts_pagination["last_page"];
$wypluj.="</LastPage>";
$wypluj.="<PostsCount>";
$wypluj.=$bazinga_blob->posts_pagination["posts_count"];
$wypluj.="</PostsCount>";
$wypluj.="</Pagination>";
$wypluj.="<Posts>";
foreach ($bb_result as $item)
{
$wypluj.="<Post>";
$wypluj.="<PostId>".$item->post_id."</PostId>";
$wypluj.="<PostAuthor>".$item->post_author."</PostAuthor>";
$wypluj.="<PostLangId>".$item->post_langid."</PostLangId>";
$wypluj.="<PostSlug>".$item->post_slug."</PostSlug>";
$wypluj.="<PostTitle>".$item->post_title."</PostTitle>";
$wypluj.="<PostGreetingPicture>".$item->post_greeting_picture."</PostGreetingPicture>";
$wypluj.="<PostGreetingVideo>".$item->post_greeting_video."</PostGreetingVideo>";
$wypluj.="<PostGreetingSound>".$item->post_greeting_sound."</PostGreetingSound>";
$wypluj.="<PostShort>".$item->post_short."</PostShort>";
$wypluj.="<PostBody>".$item->post_body."</PostBody>";
$wypluj.="<PostDate>".$item->post_date."</PostDate>";
$wypluj.="<PostPublished>".$item->post_published."</PostPublished>";
$wypluj.="<PostSticky>".$item->post_sticky."</PostSticky>";
$wypluj.="<PostComments>".$item->post_comments."</PostComments>";
$wypluj.="<PostProtected>".$item->post_protected."</PostProtected>";
$wypluj.="</Post>";
}
$wypluj.="</Posts>";
}
echo $wypluj;
The error comes from your browser and indicates that your XML is malformed.
Setting the application/xhtml+xml header tells the browser to process the document as serious XML. XML needs to be "well-formed", i.e. it must not contain any syntax errors. Apparently you do have a syntax error on line 1 at column 73, which makes the browser abort the attempt to process the document.
For this reason it's a pain to hand-code XML, you should really look into a library that takes care of the well-formedness for you, like PHP's own XMLWriter.
Have you validated your XML?
http://friendsofed.infopop.net/4/OpenTopic?a=tpc&s=989094322&f=5283032876&m=4521066061
I'm honestly not sure what you're trying to do with the header, it's not any Ajax method I've ever been taught. The header method you're doing looks just a few lines short of outputting the XML to a download prompt.
Here's my favorite way to do AJAX. Simple, understandable, and quick.
Include Jquery.
Setup your data--whether by form with a Serialize (gets form data into a Javascript Variable) or by just setting some variables as it seems you're doing above.
Send via Jquery Ajax to a separate processing page. The page will receive the data you setup as a $_REQUEST variable, with the method depending on whether you defined it as a POST or not (defaults to a GET)
The processing page --does-- stuff with the REQUEST data and may or may not respond back to the page. This is where you can do stuff like update divs, alert that it worked, etc.
Here's a great tutorial. Focus on the code under "Hello Ajax, Meet Jquery"
If you get yourself any more of those mushrooms, a PHP familiar way to do AJAX is with XAJAX. It allows you to do asynchronous calls to PHP functions. Be aware, though, that the forums are not the most english-friendly and documentation is a bit cryptic.

onbeforeprint() and onafterprint() equivalent for non IE browsers

I want to send some info back to my database when a user prints a certain web page. I can do this in IE with onbeforeprint() and onafterprint() but I would like to browser agnostic way of doing the same thing. Don't care which combination of technologies I have to use (PHP, MySQL, JavaScript, HTML) so long as it gets done. Any ideas?
EDIT:
Still having some problems with this. I tried the putting my function in my Print.css as an image, but I am messing it up some how. Then I tried just adding a event listener, but I cannot get that to work quite right either. If anyone can provide some more details on how I might call a function right before print in ANY browser I would appreciate it.
EDIT:
I am giving up on this for now, I have settled with another way of doing what I want. I look forward to the day when FireFox supports onbeforeprint() and onafterprint().
Many browsers now support window.matchMedia. This API allows you to detect when CSS media queries go into effect (e.g., rotating the screen or printing the document). For a cross-browser approach, combine window.matchMedia with window.onbeforeprint/window.onafterprint.
The following may result in multiple calls to beforePrint() and afterPrint() (for example, Chrome fires the listener every time the print preview is regenerated). This may or may not be desirable depending on the particular processing you're doing in response to the print.
if ('matchMedia' in window) {
// Chrome, Firefox, and IE 10 support mediaMatch listeners
window.matchMedia('print').addListener(function(media) {
if (media.matches) {
beforePrint();
} else {
// Fires immediately, so wait for the first mouse movement
$(document).one('mouseover', afterPrint);
}
});
} else {
// IE and Firefox fire before/after events
$(window).on('beforeprint', beforePrint);
$(window).on('afterprint', afterPrint);
}
More: http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/
I m not sure other browsers will allow you to. You could of course specify an image somewhere in a print stylesheet, which probably only will be called on a print, for the onbeforeprint
Try masking the native window.print() with your own...
// hide our vars from the global scope
(function(){
// make a copy of the native window.print
var _print = this.print;
// create a new window.print
this.print = function () {
// if `onbeforeprint` exists, call it.
if (this.onbeforeprint) onbeforeprint(this);
// call the original `window.print`.
_print();
// if `onafterprint` exists, call it.
if (this.onafterprint) onafterprint(this);
}
}())
Updated: comments.
I think that it's simply not possible to this properly. Or at least - not with any technology I know nor with any of the answers given previously.
Both using onafterprint and using serverside dynamic-image-generating script would tell you that the page was printed even when the visitor merely went to print preview mode and then canceled out.
However, I would like to learn how to get the proper information, so that I can be sure that page was actually printed.

Categories