0

プッシュ通知をいじっていて、データベースに変更があるたびにページを更新したいと考えています。

私はhttp://www.screenr.com/SNHからこれを持っています:

<?php
$filename = dirname(__FILE__).'/data.php';

$lastmodif = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
$currentmodif = filemtime($filename);

while ($currentmodif <= $lastmodif) {
  usleep(10000);
  clearstatcache();
  $currentmodif = filemtime($filename);
}

$response = array();
$response['msg'] = file_get_contents($filename);
$response['timestamp'] = $currentmodif;
echo json_encode($response);
?>

私の data.php は、JSON ファイルからデータを取得するスクリプトです。

<script>function itnews_overview() {
    $.getJSON('/ajax.php?type=itnews_overview', function(data) {
        $.each(data.data, function(option, type) {
            $('.bjqs').append('<li><span class="date">'+ type.submitted +'<br />'+     type.time +'</span><h2>' + type.title + '</h2><p>' + type.content + '</p></li>');
        });

    });

}
</script>

<script>
  itnews_overview();
</script>
<div id="news">
  <ul class="bjqs"></ul>
</div>

更新: index.php からのコード:

<script type="text/javascript">

  var timestamp = null;

  function waitForMsg() {
$.ajax({
  type: "GET",
  url: "getData.php?timestamp=" + timestamp,
  async: true,
  cache: false,

  success: function(data) {
    var json = eval('(' + data + ')');
    if(json['msg'] != "") {
      $(".news").html(json['msg']);

    }


    timestamp = json['timestamp'];
    setTimeout('waitForMsg()',1000);        
  },

  error: function(XMLHttpRequest, textStatus, errorThrown){
    setTimeout('waitForMsg()',15000);
  }

});
  }

  $(document).ready(function(){
  waitForMsg();
});

</script>

データベースに何かを追加してもこのファイルは保存されないため、filemtime は機能しません — 新しい行がテーブルに追加されたかどうかを確認する別の方法はありますか?

更新: SSE でこれを解決しようとしています。index.php と send_sse.php の 2 つのファイルがあります ( http://www.developerdrive.com/2012/03/pushing-updates-to-the-web-page-with-html5-server-sent-eventsからのインスピレーション) / )

index.php:

<div id="serverData">Content</div>
<script type="text/javascript">
//check for browser support
if(typeof(EventSource)!=="undefined") {
    //create an object, passing it the name and location of the server side script
    var eSource = new EventSource("send_sse.php");
    //detect message receipt
    eSource.onmessage = function(event) {
        //write the received data to the page
        document.getElementById("serverData").innerHTML = event.data;
    };
}
else {
    document.getElementById("serverData").innerHTML="Whoops! Your browser doesn't receive server-sent events.";
}
</script>

send_sse.php:

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$url = "content.json";
$str = file_get_contents($url);
$data = json_decode($str, TRUE);
//generate random number for demonstration
//echo the new number
echo "data: " . json_encode($data);


ob_flush();
?>

ただし、これは機能していないようです。これはおそらく、SSE がプレーン テキスト データを必要とするためです。それを行う方法を理解できず、そのコンテンツをいくつかの HTML タグでラップします。

更新:わかりました。VDP のおかげで、SSE と連携するようになりました。私は次のものを持っています:

$sql= "SELECT title, content, submitted FROM `flex_itnews` where valid = 1 order by submitted desc";
$query= mysql_query($sql);
setlocale(LC_ALL, 'da_DK');
while($result = mysql_fetch_array($query)){
    echo "data: <li><span class='date'>". strftime('%e. %B', strtotime($result['submitted'])) ."<br />kl. ". strftime('%H.%M', strtotime($result['submitted'])) ."</span><h2>" . $result['title']. "</h2><p>" . $result['content'] ."</p></li>\n";
}

ただし、何か新しいものを追加すると、単にエコーされdata: data: dataます。ページを更新すると、正しく表示されます。

更新: livequery プラグインの使用:

    <script>
      var source = new EventSource('data2.php');
      source.onmessage = function (event) {
        $('.bjqs').html(event.data);
      };

      $('#news').livequery(function(){
        $(this).bjqs({
          'animation' : 'slide',
          'showMarkers' : false,
          'showControls' : false,
          'rotationSpeed': 100,
          'width' : 1800,
          'height' : 160
        });
      });

  </script>

更新:デリゲート()を使用しようとしています

    <script>
      $("body").delegate(".news", "click", function(){
        $("#news").bjqs({
          'animation' : 'slide',
          'showMarkers' : false,
          'showControls' : false,
          'rotationSpeed': 100,
          'width' : 1800,
          'height' : 160
        });
                var source = new EventSource('data2.php');
      source.onmessage = function (event) {
        $('.bjqs').append(event.data);
      };
      });
  </script>
4

3 に答える 3

2

はい!複数の(より良い)方法があります:

  1. websocket (最適なソリューションですが、古いブラウザやモバイル ブラウザではサポートされていません)
  2. サーバー送信イベント (SSE) (ポーリングの一種ですが、要求されたタスク用に最適化されています)
  3. ロングポーリング(あなたがやっているように)
  4. フラッシュソケット
  5. 他のプラグインベースのソケットのもの
  6. ajax ポーリング

以前にそれに関する例を含む別の回答を投稿しました

いくつかの輸送方法をリストしました。websockets が理想的で (サーバーとクライアント間の唯一の双方向通信であるため)、SSE が私の 2 番目の選択肢です。$.getJSONメソッドは必要ありません。全体的な考え方は同じになります。

サーバー側(あなたの場合はphp)で、データベースに変更を問い合わせます。データを JSON として返します (json_encode(data)それが可能です)。クライアント側では、JSON をデコードします (JSON.parse(data)それが可能です)。受け取ったデータを使用して、ページを更新します。

サーバーに大量のリクエストを行っているため、あなたのようなポーリングだけでオーバーヘッドが増加します。

SSEはもっと「配信を購読したい」「聞くのをやめたい」です。=> オーバーヘッドが少ない

Websockets はもっと: 「私は接続をセットアップします。私はサーバーがリッスンすることを話します。サーバーはクライアントがリッスンすることを話します」 全二重接続。=>最小オーバーヘッド

SSEコードの例

クライアントが移動するページ (index.html や index.php など)

これは、次の JavaScript を含む通常の HTML ページです。

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
    <script>
        //javascript:
        var source = new EventSource('data.php');
        source.onmessage = function (event) {
            //here you do the stuff with the received messages.
            //like log it to the console
            console.log(event.data);
            //or append it to div
            $('#response').append(event.data);
        };
    </script>
</head>
<body>
    <div id="response"></div>
</body>
</html>

「data.php」ページ:

<?php
/* set the header first, don't echo/print anything before this header is set! Else the default headers will be set first then this line tries to set the headers and results in an error because the header is already set. */
header("Content-Type: text/event-stream\n\n");

//query the database
$sql= "SELECT COUNT(*) FROM `messages`";
$query= mysql_query($sql);
$result = mysql_fetch_array($query);
$count = $result[0];

//return the data
echo "data: " . $count. "\n";
?>

したがって、必要なのはその 2 ページだけです。

アップデート:

私は更新ではなくあなたのコメントを見ただけでした..申し訳ありません;)

使用する.delegate()場合は、 body を使用しないでください。ただし、ツリーのできるだけ上のセレクターを試してください(.bjqsあなたの場合)。

あなたの場合、ライブ、デリゲート、オン、またはそのすべてさえ必要ありません! コンテンツが更新されたら、bjqs を再度適用するだけです。

  var source = new EventSource('data2.php');
  source.onmessage = function (event) {
    $('.bjqs').html(event.data);
    $("#news").bjqs({
      'animation' : 'slide',
      'showMarkers' : false,
      'showControls' : false,
      'rotationSpeed': 100,
      'width' : 1800,
      'height' : 160
    });
  };

常に bjq を再初期化していて、動的に更新されるコンテンツを処理するように作成されていないため、これも問題を引き起こします。あなたができることは、新しいデータがあればデータのみを送信することです(phpで)。更新されていない場合は、呼び出しが空を返すかどうかを確認します。

  var source = new EventSource('data2.php');
  source.onmessage = function (event) {
    if(event.data !=""){
        $('.bjqs').html(event.data);
        $("#news").bjqs({
          'animation' : 'slide',
          'showMarkers' : false,
          'showControls' : false,
          'rotationSpeed': 100,
          'width' : 1800,
          'height' : 160
        });
    }
  };
于 2012-09-17T13:54:17.313 に答える
0

テーブル内の行数をカウントし、行数が変更されているかどうかを確認できます。

于 2012-09-17T13:56:14.257 に答える
0

コードを掘り下げすぎずに、タイトルの質問に答えます。

最後に変更された列をテーブルに追加します。これには、行が追加または変更されるたびに更新される組み込みの mysql トリガーがあります。

ALTER TABLE `yourTable`
    ADD COLUMN `last_modified` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    ADD INDEX (`last_modified`);

そして、次のようにクエリします。

SELECT * FROM yourTable where last_modified > ?

(「?」は、最後に照会されたタイムスタンプに置き換える pdo プレースホルダーです)

于 2012-09-19T10:49:52.187 に答える