Today I have a working example for you. I try to highlight the important parts.
First of all the PHP File that "does something", I called it progress.php:
progress.php
<?php
if (strlen(session_id()) === 0) {
session_start();
}
makeProgress();
function makeProgress() {
$progress = 0;
$max = 100;
for ($i = 1; $i <= $max; $i++) {
if (isset($_SESSION['progress'])) {
session_start(); //IMPORTANT!
}
$progress++;
$_SESSION['progress'] = $progress;
session_write_close(); //IMPORTANT!
sleep(1); //IMPORTANT!
}
}
A Session is opened for our progress to be stored in.
Now the function makeProgress is started and runs a loop that count progress up and sleeps for a second, before it counts up again.
The Session is write_closed, the script sleeps for a second and after that the session is started again. This is important to give other workers access to Session and working time. Without closing, the Session would be stalled until the makeProgress loop is finished, without sleep no other script gets "Servertime" to do something and would be stalled till the end of the loop.
Next the PHP File that gets the progress:
getProgress.php
<?php
if (strlen(session_id()) === 0) {
session_start();
}
if (isset($_SESSION['progress'])) {
echo $_SESSION['progress'];
if ($_SESSION['progress'] == 100) {
unset($_SESSION['progress']);
}
} else {
echo '0';
}
This is quite simple, it just starts the session and returns whats in our Session Variable. It also unsets the Variable if 100% is reached.
Now the glue, Javascript file:
progress.js
$('document').ready(function () {
$('#startProgress').click(function () {
getProgress();
console.log('startProgress');
$.ajax({
url: "progress.php",
type: "POST",
data: {
'startProgress': 'yes'
},
async: true, //IMPORTANT!
contentType: false,
processData: false,
success: function(data){
if(data!==''){
alert(data);
}
return false;
}
});
return false;
});
});
function getProgress() {
console.log('getProgress');
$.ajax({
url: "getProgress.php",
type: "GET",
contentType: false,
processData: false,
async: false,
success: function (data) {
console.log(data);
$('#progressbar').css('width', data+'%').children('.sr-only').html(data+"% Complete");
if(data!=='100'){
setTimeout('getProgress()', 1000);
}
}
});
}
Setting your startProgress ajax call to async: true is important, otherwise your Browser would stall and wait for the long executing script to respond.
The getProgress function is started when you click the button and executed again every Second as long as the returned data is not 100. Simple.
In the end there is an html file, making progress visible:
progress.html
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="progress.js"></script>
</head>
<body>
<form action="progress.php" method="POST" >
<input id="startProgress" type="submit" name="startProgress" value="start progress"/>
</form>
<div class="progress" style="margin-top:100px">
<div class="progress-bar active" id="progressbar" role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 0%; background-color: #399;">
<span class="sr-only">0% Complete</span>
</div>
</div>
</body>
</html>
Now see the working example in Action and Download all those files I used here:
https://9tw.de/~testArea/progress/progress.html
Things that need to be addressed: Since the initial ajax call is async, it is possible to click it more than one time, what will cause the progress bar to fluctuate (since now there are 2 to n scripts running simultaneously and writing to the same Session Variable). You might want to block a second click until the current process is finished.
Another Thing: if you sleep every second for one second, the script execution time will double. You need to find a good compromise between executing time and progressbar updates.
There are other (even better) technics to implement progress bars, like Threading, but since Threading is quite rarely compiled into PHP, this should be the most (hoster-)compatible solution to date.
Happy Coding.