5

I want to create a progress bar for a server-side task ( written in php )

For learning purposes the example and task would be very simplistic. I would have a text field on the client page, read a number, pass it to the php script with ajax and make it calculate the sum of all numbers from 0 to number ( simplistic task that would take some time for big numbers, just to simulate some server-side work)

in the .html file I would create a timer that would call a function every n seconds getting the index that my for loop got to and update a progress bar.

My question is :
Is it possible to have in the same php file two functions , and how can I call a specific function with ajax : one that would block looping to number and another one I would call to get the current index the for-loop got to.

The code I have so far :

<!DOCTYPE html>
<html>
<head>
    <script>
        function myTimer()
        {
            var xmlhttp;
            if (window.XMLHttpRequest)
              {// code for IE7+, Firefox, Chrome, Opera, Safari
              xmlhttp=new XMLHttpRequest();
              }
            else
              {// code for IE6, IE5
              xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
              }
            xmlhttp.onreadystatechange=function()
              {
                  if (xmlhttp.readyState==4 && xmlhttp.status==200)
                    {
                        document.getElementById("percentageDiv").innerHTML=xmlhttp.response;
                        alert(xmlhttp.response);
                    }
              }
            xmlhttp.open("GET","getter.php",true);
            xmlhttp.send();
        }

        function loop(){
            var loop_index = document.getElementById("loop_nr").value;
            var xmlhttp;
            if (window.XMLHttpRequest)
              {// code for IE7+, Firefox, Chrome, Opera, Safari
              xmlhttp=new XMLHttpRequest();
              }
            else
              {// code for IE6, IE5
              xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
              }
            xmlhttp.onreadystatechange=function()
              {
                  if (xmlhttp.readyState==4 && xmlhttp.status==200)
                    {
                        document.getElementById("sumDiv").innerHTML="Total sum = " + xmlhttp.response;
                        clearInterval(myVar);
                    }
              }
            xmlhttp.open("GET","server_side.php?nr="+loop_index,true);
            xmlhttp.send();
            var myVar=setInterval(function(){myTimer()},1000);
        }
    </script>
</head>
<body>
<div id="percentageDiv"> Percentage div</div>
<div id="sumDiv"></div>
<input type="text" id="loop_nr">
<input type="submit" onclick="loop()">

</body>
</html>

server_side.php

<?php
    session_start();
    $index=$_GET["nr"];
    $progress = 0 ;
    $sum = 0 ;

    for ($i = 1; $i <= $index; $i++) {
        $sum = $sum + $i;
        $progress++;
        $_SESSION['progress'] = $progress;
    }
    echo $sum;
?>

getter.php

<?php
    session_start();
    $progress = $_SESSION['progress'];
    echo $progress;
?>

Thank You!

4
  • Have you done ajax calls to php before? This is not different from it, only that you have to save the value of the progress in the $_SESSION to persist it. Commented Dec 8, 2013 at 11:52
  • I am actually new to ajax and php, I'll post the code I have so far Commented Dec 8, 2013 at 11:54
  • 1
    I was just thinking about that. My question is how can I call with ajax a specific function from php? Commented Dec 8, 2013 at 11:55
  • I think the PHP you have is more important than the AJAX. Post it too. Commented Dec 8, 2013 at 11:59

2 Answers 2

13

Not only one question in here

Your question would be two:

  • How can I do AJAX calls to specific functions in PHP?
  • How can I do a progress bar with AJAX?

How can I do AJAX calls to specific functions in PHP?

Your AJAX code is fine. The only thing you have to do in your PHP is receive this call.

Look at your request. You send a variable nr with your request:

server_side.php?nr="+loop_index

That will help us in the php code to determine that this is an AJAX call to do the sum operation. Now in the PHP:

<?php session_start();

//We look at the GET php variable to see if the "nr" is coming
if(isset($_GET['nr'])) {
    //Its coming!. Now we procede to call our function to sum
    sum($_GET['nr']);
}

function sum($nr) {
    $progress = 0 ;
    $sum = 0 ;
    for ($i = 1; $i <= $nr; $i++) {
       $sum = $sum + $i;
       $progress++;
       $_SESSION['progress'] = $progress;
    }
    echo $sum;
}

Thats it.

How can I do a progress bar with AJAX?

We need to make other AJAX call to request the progress to PHP.
First, we do another AJAX call to retrieve the progress with a timer!

    var timer;
    
    //try to delete duplications. Do a generic function that does the request to php
    function makeRequest(toPHP, callback) {
        var xmlhttp;
        if (window.XMLHttpRequest)
          {// code for IE7+, Firefox, Chrome, Opera, Safari
          xmlhttp=new XMLHttpRequest();
          }
        else
          {// code for IE6, IE5
          xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
          }
        xmlhttp.onreadystatechange=function()
          {
              if (xmlhttp.readyState==4 && xmlhttp.status==200)
                {
                    callback(xmlhttp.response);
                }
          }
        xmlhttp.open("GET",toPHP,true);
        xmlhttp.send();
     }

     function loop() {
         var loop_index = document.getElementById("loop_nr").value;
         makeRequest("server_side.php?nr="+loop_index, function(response) {
             document.getElementById("sumDiv").innerHTML="Total sum = " + response;
             clearInterval(timer);
         });
         timer=setInterval(makeRequest("getter.php", function(response) {
             document.getElementById("percentageDiv").innerHTML=response;
          }),1000);
     }

Then in the php side we retrieve this call as we did before and echo the $_SESSION['progress'] (as you already have)

<?php
    session_start();
    $progress = $_SESSION['progress'];
    echo $progress;
?>

And that's it!

Edit: Sessions must not be saved to a file (default PHP behaviour) because if you do that the "progress" AJAX will be blocked. You should store your sessions in a key-value database such as Redis to achieve parallelism and horizontal scalability.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, you are helping me very much so far. I've edited the code in the question. Could you take a look and tell me why my progressDiv is getting updated just when the sum-task got finished, until then it's blocked. ( I get the alert in myTimer, after the task is finished)
Problem solved - I was having a blocking problem because I wasn't closing the session so that the ajax requests where not parallel. I am marking your question as an answer because you helped me a lot! Thank you!
I'd be curious to know how the sample code can work. Since both PHP scripts need the session to work, I don't see how they can be made to run parallel...
@Goozak Sessions must not be saved to a file (default PHP behaviour) because if you do that the "progress" AJAX will be blocked. You should store your sessions in a key-value database such as Redis to achieve parallelism and horizontal scalability.
I'm not sure this will work, as without the use of session_write_close(), the session handler 'write' method is only called when PHP terminates. So all previous value updates to $_SESSION['progress'] will be ignored, only the very last $progress value will be stored.
-7

Here is the solution to made progress bar in PHP without javascript only on server side:

 echo "<div style=\"float:left;\">Start... </div>";
 for ($i = 0; $i<20; $i++){
    echo '<div style="float:left;background-color:red;height:20px;width:'.$i.'px"></div>';
    ob_flush();
    flush();
    usleep(100000);
 }
 echo "<div style=\"float:left\"> Done!</div>.";
 ob_end_flush();exit;

1 Comment

please do not copy this. it really is a pain too see code like this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.