nigoblog

暫定無職のブログ

PHPとAjaxで擬似的にリアルタイム通信を実現する。

先日QiitaQiita [キータ] - プログラマの技術情報共有サービスが主催するハッカソンに参加して参りました。
結果はなんと優勝しちゃいました!!

テーマは「マルチスクリーンで動作するアプリケーション」というわけで、

一つの画面を複数のデバイスで操作するという感じのアプリケーションを作成しました。
その時に端末のデバイスでのイベントをリアルタイムでメインの画面に反映させるということをPHPAjaxで行いました。

具体的なPHP, Ajax技術利用法を書いていきます。

アイディア

具体的にどんなものかというと、一つのメイン画面にバーが2つあり、端末を振るとそのバーが変化します。
2台以上の端末を使って、バーを二手に分け、どちらがより振ったかを競うようなアプリケーションです。
端末側はチームメンバーで私はメインの方を担当しました。

PHP, Ajax実現アルゴリズム

擬似的にリアルタイム通信を実現する流れは次のようになります。

  1. 端末側でテーブルを更新するAPIを叩く
  2. メイン側でテーブルのデータを取得するAPIを叩く
  3. 取得した結果をDOM操作する
  4. 2~3を一定間隔で常に行う

以上の流れで擬似的にリアルタイムが実現できます。
擬似的なのはテーブルが更新されたのをキッカケにメイン側でアクションが起きるわけではないからです。
もっと本格的なリアルタイムを実現したい場合はwebsocketを使う必要があります。

端末側

まず端末がわではテーブルを更新するAPIを叩きます。
今回の場合「振った」というイベントでAPIを叩きます。
そのAPIのコードが以下になります。

public function api(){
	header("Content-Type: application/json; charset=utf-8");
	$data['point'] = $_GET['point'];
	$data['team']  = $_GET['team'];

	$this->load->model('supporter_model', 'supporter');
	$this->supporter->insertPoint($data['point'], $data['team']);

	$json = json_encode($data);
	print_r($json);
}

JSONでのリターンがあるのは正常に通信が行われているかどうかを確認するためです。
モデルは省略しますが、

$this->supporter->insertPoint($data['point'], $data['team']);

の部分でテーブルを更新しています。
ちなみに今回codeigniterを利用しております。

メイン側

テーブルのデータを取得し、JSONで返します。

public function apiPointGet(){
	header("Content-Type: application/json; charset=utf-8");
	$this->load->model('supporter_model', 'supporter');
	$data['pointSumA'] = $this->supporter->selectPoint('A');
	$data['pointSumB'] = $this->supporter->selectPoint('B');

	$result_array = array(
		'teamA' => $data['pointSumA']['SUM(point)'],
		'teamB' => $data['pointSumB']['SUM(point)']
	);

	$result = json_encode($result_array);
	print_r($result);
}

同様に説明を省きますが、下記でデータを取得します。

$data['pointSumA'] = $this->supporter->selectPoint('A');
$data['pointSumB'] = $this->supporter->selectPoint('B');

このAPIを随時叩くことにより擬似的にリアルタイムを実現します。

取得した結果を一定間隔でDOM操作する

ここが今回のメインとなります。JS部分だけを説明します。

function graph(){
    function reload(){
	$.getJSON(
		'./supporters/apiPointGet', // アクセス先のURL
		function(data, status) {
			teamTotal = Number(data.teamA) + Number(data.teamB);
			teamA = (Number(data.teamA) * 100) / Number(teamTotal);
			teamB = (Number(data.teamB) * 100) / Number(teamTotal);
			$('#teamA').css('width', teamA + '%');
			$('#teamB').css('width', teamB + '%');
			console.log(teamA);
			console.log(teamB);
		}
	);
    }	
var teamA = 0;
var teamB = 0;
timer = setInterval(reload, 100);	
}

簡単ですが以上になります。
reload()という関数をsetIntervalで100ミリ秒感覚で実行します。
reload()内は上記で説明したテーブルの内容を取得し、JSONをパースしcss操作をする処理となります。


以上、簡単ですが、PHPAjaxで擬似的にリアルタイムを実現する方法でした。
ただしあくまで擬似的なので今後node.jsなので本格リアルタイム通信を実現させたいと思います!!