2

TL;博士

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


设置

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

我创建了一个管理后端,可以轻松粘贴到密钥列表中,或上传它们的文件。

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

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

现在,我不介意花这个时间。我不需要优化上传以使用一个查询等,但我想有一些实际的反馈,所以我知道上传已经走了多远。


问题

当我上传密钥时,我希望能够每隔几秒或百分比刻度更新我的视图中的进度条或计数器(使用 current $index

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

4

3 回答 3

8

使用 PHP,实际上有两种选择,而无需使用 Web Sockets 或 Push-Pull 设置。这并不是真正的 Laravel 东西,它更像是一个请求 JSON“东西”的 AJAX 循环。

短轮询

Olark 将这种方法用于他们的聊天脚本。

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

长轮询

Javascript

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

控制器逻辑

当我让用户上传 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,
));

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

例子

于 2013-08-21T00:34:37.373 回答
2

您可以将其放入 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');
});
于 2013-08-20T20:35:13.133 回答
1

无论您使用 Laravel 还是 Core PHP 编写代码,都应该尝试使用Server 发送的事件。使用 SSE 很容易做到。

它基本上包括两个部分:-

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

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

然后为消息事件设置一个处理程序。您可以选择监听打开和错误:-

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(服务器端) - 您必须发送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()));

所有这些片段都是从上述链接中借用的,建议进行彻底的研究以获得清晰的理解。

干杯

于 2015-11-29T15:46:39.807 回答