1

I am stuck in this problem, about making realtime progressbar on php (without php pusher)

Let's say I have 10 rows of data, that will be inserted to database.

Now how to send the progressbar data, while also inserting to database.

I will really appreciate your answers. Thanks.

Bellow is my code example:

// script.js (client)
// This function executed when user submit form
function store() {
  // Listen Server Side Event
  let event = new EventSource('controller/store')
  
  event.addEventListener('message', response => {
    // Then update progressbar
    updateProgressbar(response.percent)
  })
  
  // Ajax to save data to database
  $.ajax({
    url: baseUrl + 'controller/store',
    type: 'POST',
    dataType: 'JSON',
    data: $('#form').serializeArray(),
    success: function(response) {
      console.log(response)
    }
  })
}


// Controller.php (server)
public function store() {
  header("Content-Type: text/event-stream");
  header("Cache-Control: no-cache");
  header("Connection: keep-alive");
  
  $total_row = count($_POST['customer']);

  for ($i = 0; $i < $total_row; $i++) {
    usleep(100000);
      
    $this->db->insert('customers', $_POST['customer'][$i]);
    
    $percent = ($i + 1) * (100 / $total_row);

    echo "event: message\n";
    echo 'data: {"status": "loading", "percent": "' . $percent . '"}';
    echo "\n\n";

    ob_end_flush();
    flush();

    if (connection_aborted()) break;
  }

  echo "event: message\n";
  echo 'data: {"status": "done", "percent": "' . $percent . '"}';
  echo "\n\n";
}
Hermes TAS
  • 41
  • 5
  • 1
    I don’t know what “PHP Pusher” is at all, but you’ve tagged this with three technologies that could be used to do this, in addition to the server server side language. Can you focus this more on to something more specific? – Chris Haas Oct 16 '21 at 02:43
  • @ChrisHaas In this case, im using php (server) and javascript (client). I try to insert data using AJAX and show progressbar using Server Sent Event. The problem is: AJAX needs JSON as response, where at the same time SSE needs Event-Stream as response. HTTP can only accept 1 type of response. – Hermes TAS Oct 16 '21 at 03:51
  • This still needs a bit more explanation, the bigger picture problem you are trying to solve. Is the progress bar going back to the client that is sending the data; or is it for other clients? Does it send all 10 rows of data at once, but each row take a very long amount of time to insert into the database? Or it sends one row at a time? – Darren Cook Oct 16 '21 at 07:42
  • AJAX doesn’t require JSON, that it just a common convention. Is the client originating this process, or just being made aware of it? Is a progress bar a literal one, or just text that is “2:10” or “20%” or similar? – Chris Haas Oct 16 '21 at 08:32
  • it is up to you, without more information on what is available on the server side you can perform periodic ajax request to check a php page giving the status, you would have to find the way to make this served php page gather the status information and how to use its response to update your client page. If you are interested in websocket, it can also be done, with php, but you would have to setup a "dedicated" server (distinct process of your current server). with php I like this one [ghedipunk on github](https://github.com/ghedipunk/PHP-Websockets) – Tuckbros Oct 16 '21 at 10:47
  • @DarrenCook 1. The progress will be returned to data sender NOT for others; 2. It sends all 10 rows of data at once which takes a long time – Hermes TAS Oct 16 '21 at 16:41
  • @ChrisHaas The progressbar is percentage (20%) – Hermes TAS Oct 16 '21 at 16:48

1 Answers1

1

Web servers and browsers will not let this work the way that you want.

The HTTP headers include the content length, which the web servers will want to know before sending the document to the client. Unless you already know exactly how long the document body will be, the server will (usually) wait until the PHP script exits before sending any information to the client.

ob_end_flush() and flush() do not send information directly to the client; the send it to the web server, which will still cache it until the entire document is ready to be sent.

And, the client side AJAX request will also wait until the entire document has been received before running the success function.

So, you need to set up something on your server that will store the progress, that is available to another script that you can call.

Your server side script should send a random token back, then continue processing php after sending http response.

Your client side script will then need to occasionally query your server using that token until either the long lived process is complete or it has failed.

You can update the client faster by using WebSockets, as Tuckbros mentioned in the comments (and I appreciate the mention of my server), but unless it's important for the user to know when the process has ended within a few dozen milliseconds, I'd suggest staying with normal Web-PHP and AJAX, as WebSockets requires some understanding of CLI-PHP and extra nuances of HTTP.

Ghedipunk
  • 1,229
  • 10
  • 22