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: messagen"; echo 'data: {"status": "loading", "percent": "' . $percent . '"}'; echo "nn"; ob_end_flush(); flush(); if (connection_aborted()) break; } echo "event: messagen"; echo 'data: {"status": "done", "percent": "' . $percent . '"}'; echo "nn"; }
Advertisement
Answer
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.