Update live data (like progress bar) in view with Laravel 4

旧时模样 提交于 2020-01-21 00:42:52

问题


TL;DR

I would like to send data to update live in a view, such as a progress bar showing the status of an action. What is the best way to do that in laravel 4?


The Setup

I'm working on a Laravel 4 based project where each user can redeem a serial key.

I've made an admin backend where I can easily paste in a list of keys, or upload a file of them.

Let's say $key_string is the string of newline-seperated keys that I've uploaded, and want to parse out to then upload the contained key strings from - here is the simplified code that adds the keys:

$key_string = rtrim($key_string);
$key_string = str_replace("\n\r", "\n", $key_string);
$keys = explode( "\n", $key_string);

foreach($keys as $index => $key) {
    Key::create(
        array( "serial" => trim($key) )
    );
}

Since the sets of keys I upload number in the thousands, this can sometimes take a good 30 seconds, during which time the admin panel naturally doesn't show anything.

Now, I don't mind it taking this time. I don't need to optimize the upload to use one query, etc, but I would like to have some actual feedback so I know how far the upload has gone.


The Question

When I upload keys, I would like to be able to update a progress bar or counter in my view every few seconds or percent ticks (using the current $index)

Is there an easy way to handle this painlessly, preferably integrated in Laravel 4? I'm assuming this would involve ajax, but can someone point me in the right direction?


回答1:


With PHP there are really two options without going to Web Sockets or Push-Pull setups. This isn't really a Laravel thing it's more of an AJAX loop that requests JSON "thing".

Short polling

Olark uses this methodology for their chat script.

setInterval(function() {
    $.getJSON("/path", function(data) {
        // update the view with your fresh data
    });
}, 5000);

Long polling

Javascript

var eventName = function() {
    $.getJSON("/path", function(data) {
        // update the view with your fresh data
        if (data.progress < 100)
            eventName();
    });
};

Controller Logic

I use this when I have users upload a CSV and are waiting for it to finish uploading and be processed.

// in your controller
$check = true;
while ($check) {
    // search database
    // compare values
    if ($newDataWasFound)
        $check = false;

    $progressFromAbove = 90;
}

return Response::json(array(
    'newData' => $array,
    'progress' => $progressFromAbove,
));

I made a screencast on this using Laravel 3 but Long Polling is PHP relevant not Laravel. https://www.youtube.com/watch?v=LDgJF77jELo

Examples

  • https://gist.github.com/clouddueling/5239153
  • https://gist.github.com/clouddueling/6296036



回答2:


You could put it in Session and get it from another link.

$key_string = rtrim($key_string);
$key_string = str_replace("\n\r", "\n", $key_string);
$keys = explode( "\n", $key_string);

$count = 0;
foreach($keys as $key) {
  Key::create(
      array( "serial" => trim($key) )
  );
  $count++;
  if($count % 5== 0) Session::put('count',$count);
}


//route.php
Route::get('/count', function()
{
   if( Session::has('count'))
        return Session::get('count');
});



回答3:


Whether you code using Laravel or Core PHP, you should give Server sent events a try. It is easily doable using SSE.

It basically includes two parts:-

1. Javascript API (Client side) - You will have to subscribe to an event stream, create an EventSource object and pass it the URL of your stream like this:-

if (!!window.EventSource) {
  var source = new EventSource('stream.php');
} else {
  // Result to xhr polling :(
}

Then setting up a handler for the message event. You can optionally listen for open and error:-

source.addEventListener('message', function(e) {
  console.log(e.data);
}, false);

source.addEventListener('open', function(e) {
  // Connection was opened.
}, false);

source.addEventListener('error', function(e) {
  if (e.readyState == EventSource.CLOSED) {
    // Connection was closed.
  }
}, false);

2. PHP (Server side ) - You will have to send Content-Type: text/event-stream header and then push the response as and when processed, in predefined format like this:-

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.

/**
 * Constructs the SSE data format and flushes that data to the client.
 *
 * @param string $id Timestamp/id of this connection.
 * @param string $msg Line of text that should be transmitted.
 */
function sendMsg($id, $msg) {
  echo "id: $id" . PHP_EOL;
  echo "data: $msg" . PHP_EOL;
  echo PHP_EOL;
  ob_flush();
  flush();
}

$serverTime = time();

sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));

This all snippets is borrowed from aforementioned link and a thorough study is recommended for crystal clear understanding.

Cheers



来源:https://stackoverflow.com/questions/18344343/update-live-data-like-progress-bar-in-view-with-laravel-4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!