使用 Laravel 4 更新实时数据(如进度条)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18344343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 08:18:38  来源:igfitidea点击:

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

phpajaxlaravellaravel-4

提问by Johannes

TL;DR

TL; 博士

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?

我想发送数据以在视图中实时更新,例如显示操作状态的进度条。在laravel 4中做到这一点的最佳方法是什么?



The Setup

设置

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

我正在开发一个基于 Laravel 4 的项目,每个用户都可以兑换一个序列号。

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_stringis 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是我上传的以换行符分隔的键字符串,并且想要解析然后从中上传包含的键字符串 - 这是添加键的简化代码:

$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.

由于我上传的密钥集数以千计,这有时可能需要 30 秒,在此期间管理面板自然不会显示任何内容。

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)

当我上传密钥时,我希望能够每隔几秒或百分比刻度(使用当前$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?

有没有一种简单的方法可以轻松处理这个问题,最好是集成在 Laravel 4 中?我假设这将涉及 ajax,但有人可以指出我正确的方向吗?

回答by Michael J. Calkins

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".

对于 PHP,实际上有两种选择,无需 Web Sockets 或 Push-Pull 设置。这实际上并不是 Laravel 的事情,它更像是一个请求 JSON“事物”的 AJAX 循环。

Short polling

短轮询

Olark uses this methodology for their chat script.

Olark 在他们的聊天脚本中使用这种方法。

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

Long polling

长轮询

Javascript

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.

当我让用户上传 CSV 并等待它完成上传和处理时,我会使用它。

// 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

我使用 Laravel 3 对此进行了截屏,但长轮询与 PHP 相关,而不是 Laravel。 https://www.youtube.com/watch?v=LDgJF77jELo

Examples

例子

回答by Yahia Reyhani

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

你可以把它放在 Session 中并从另一个链接获取它。

$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');
});

回答by Jatin Dhoot

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

无论您使用 Laravel 还是 Core PHP 进行编码,您都应该尝试一下服务器发送的事件。使用 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:-

1. Javascript API(客户端)-您必须订阅事件流,创建一个 EventSource 对象并将您的流的 URL 传递给它,如下所示:-

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-streamheader and then push the response as and when processed, in predefined format like this:-

2. PHP(服务器端)-您必须发送Content-Type: text/event-stream标头,然后在处理时以预定义的格式推送响应,如下所示:-

<?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

干杯