PHPからストリーム出力して Ajax でリアルタイム更新する

Ajax から PHP を呼び出すとき、
普通の方法だと1回ぽっきりのレスポンスしか受け取れません。

でも次みたいな場合、リアルタイムにレスポンスを受け取りたいです。

  • データを常に画面上で更新したい場合
  • Twitterタイムライン的なのを作る場合
  • とにかくリアルタイム通信したい場合

僕もあるWebアプリを作っていて、リアルタイムレスポンスが必要でした。

ここでは自分の記憶の整理も兼ね、
PHPでストリーム出力して Ajax でリアルタイム更新する方法 を紹介します。

ストリーム出力の基本さえ知っていれば、意外と簡単にできます。

手順0.PHP + Ajax でリアルタイム更新する基本の流れ

リアルタイム更新をする処理、これは2つの部分に分けられます。

  1. サーバー側(データを更新する)
  2. ブラウザ側(データを受け取る)

サーバー側では PHP を使ってストリーム出力、
ブラウザ側では Ajax を使ってそれを受け取るみたい流れ

ここではリアルタイム更新の例として、 1.PHPから現在時刻をレスポンスとして返す ⇒ 2.ブラウザ側でデータを受け取る ⇒ 3.コンソールに表示 みたいなコードを書いてみます。

手順1.PHP側でストリーム出力するコードを書く

まずはリアルタイム更新するPHPコードの書き方について

大事なポイントは次の3つ

1. Transfer-Encoding: chuncked  をヘッダーに指定
2. データをそれぞれのチャンク(塊)に分けて出力
3. データ出力後に ob_flush  と flush  実行

言葉だと分かりにくいので、実際のコードを見た方が分かりやすいです。

 

例えば次がそのコード例、
1秒おきにレスポンスを返すコードを書いてみました。

▼ stream.php

最初にも書いたように、最重要なのが3つのポイント

  • ヘッダーの指定
    データを塊で出力できるように Transfer-encoding: chunked  を指定してる。
    あと Content-type  に対して application/octet-stream  を指定
  • データをチャンクに分けて出力
    コード内の output_chunk()  という関数。ここでチャンクの長さとチャンクデータ自体を出力してる(必ず改行が必要)
  • データ出力後に ob_flush と flush 実行
    これをしないとブラウザ側でリアルタイムに受け取れないので注意!!

あと途中でタイムアウトしないように、 set_time_limit  も設定してます。
ここでは1時間にしてますが、必要ならもっと長く設定しておけばOK( 0 で無限)

手順2.Ajax側からリアルタイム出力を受け取る

次に Ajax から PHP を呼び出し、リアルタイムでレスポンス受け取り

ここでは次の3ステップで受け取ることにします。

  1. まず Ajax から PHP を呼び出す
  2. 定期的にレスポンスを監視
  3. レスポンスに変化があれば表示する

上の手順でAjaxからリクエストを送るのは1回だけ。
それ以降は setInterval  を使って変化がないかどうか監視するだけです。

 

実際にリアルタイム更新するコード例は次の通りです。

▼ ストリーム出力を受け取り、表示するコード例

何をしてるかはコード内のコメント参照

あと大事な所だけ箇条書きすると、こんな感じです。

  • Ajax通信開始したかを監視する
    この監視には xhrFields  の onloadstart  イベントを使っている。Ajax通信が始まったらリアルタイム処理を連続で受け取る処理を開始する
  • タイマーでレスポンス開始
    ここでは1秒ごとにレスポンスに変化がないか監視している。もし変化があれば、
    差分を切り出してコンソール表示している

他にも大事なところはあるけど、最重要なのがこの2点ですね。

Ajax通信を行うのは1回だけで、それ以降はレスポンスが延々と受け取れます。

ここまでのまとめ

以上、PHP+Ajaxでリアルタイム更新する方法でした。

Twitter的なタイムラインを作ったり、リアルタイム更新の掲示板を作ったり・・・

色々な場面で役立ちそうなテクニックです。

でもやり方が特殊なので、忘れないようにメモしておきます。ではまた(^^)/~~~バイバイ

Commentsこの記事についたコメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください