チャット - Flash(ActionScript)とPHPの連携入門
目次
実行画面
Flash によるチャットアプリケーションです。自動リロード時間は10秒となっています。チャット画面へ
ソースダウンロード
今回のポイント
- LoadVars クラスによる PHP との連携
- キーリスナー
- TextField クラスの使い方
画面作成
ファイル名「chat.fla」で新規 Flash ドキュメントを作成してください。そこにステージ・ステージに乗せるシンボルなどを作ってゆきます。ステージのプロパティ
最初にステージのプロパティを設定します。この解説で使っているムービーでは、サイズを「550×400」、背景色を「#FF7315」、フレームレートを「15fps」としています。背景の作成
1フレーム目に以下のような感じで適当に背景を描きます。
下図の枠がギザギザになっている四角形は、矩形ツールで枠線の色を背景色と同じにし、線のスタイルをギザギザの線にしています。他にも、例えば点線にすると切手のような形になります。

テキストフィールドの作成
次に、テキストツールを使い、以下の図のように4つのエリアを作成します。
作成したら、各々のプロパティを設定します。変数の欄は空にしてください。
-左上はダイナミックテキスト、インスタンス名を「user_txt」、行タイプを「複数行」とします。
-右上はダイナミックテキスト、インスタンス名を「log_txt」、行タイプを「複数行」とします。
-左下はテキスト入力、インスタンス名を「name_txt」、行タイプを「単一行」とします。
-右下はテキスト入力、インスタンス名を「msg_txt」、行タイプを「単一行」とします。
フレームアクションの作成
1フレーム目をクリックして、以下の ActionScript を記述します。
System.useCodepage = true;
var sl = new LoadVars(); // 送受信データ
var timer = 0; // リロードタイマ
user_txt.tabEnabled = false;
log_txt.tabEnabled = false;
Key.addListener(msg_txt);
sl.load("chat.php");
// Enterキーの処理
msg_txt.onKeyDown = function() {
if (Key.getCode() == Key.ENTER) {
if (name_txt.length == 0) name_txt.text = "名無しさん";
sl.name = name_txt.text;
sl.msg = msg_txt.text;
sl.sendAndLoad("chat.php?rn=" + Math.random(), sl);
msg_txt.text = "";
}
}
// PHPからデータを受信したときの処理
sl.onLoad = function() {
log_txt.text = this.log;
user_txt.text = this.user;
log_txt.scroll = log_txt.maxscroll;
timer = 0;
}
// 毎フレーム処理
onEnterFrame = function() {
// 10秒でリロード
if (++timer > 15 * 10) {
sl.load("chat.php?rn=" + Math.random());
}
}
完成したらパブリッシュして chat.swf と chat.html をサーバにアップロードしてください。サーバプログラム(PHP)の作成
次にチャットデータを送受信するPHPプログラムを作成します。以下のソースを入力してください。
<?php
$lines = array();
$user = '';
$log = '';
$fp = fopen('chat.txt', 'r+');
flock($fp, LOCK_EX);
for (;;) {
$line = fgets($fp);
if (!$line) break;
array_push($lines, $line);
}
$time = time();
if ($_POST['msg']) array_push($lines, "{$_POST['name']}\t{$_POST['msg']}\t$time\n");
if (count($lines) > 50) array_shift($lines);
rewind($fp);
ftruncate($fp, 0);
foreach ($lines as $l) fputs($fp, $l);
fclose($fp);
foreach ($lines as $l) {
list($n, $m, $t) = explode("\t", $l);
$t = rtrim($t);
// 3分以上発言していないユーザーはオフライン
if ($time - $t < 180) {
if (!strstr($user, $n)) $user .= "$n\n";
}
$log .= "$n> $m(" . date("m/d H:i:s", $t) . ")\n";
}
print "user=" . urlencode($user);
print "&log=" . urlencode($log);
?>
完成したら「chat.php」という名前でサーバにアップロードしてください。ログファイルの作成
チャットのログを保存するファイルを作成します。空のテキストファイル「chat.txt」を作成してサーバにアップし、属性変更から「その他」に書込許可属性を与えてください。実行
以上が完成したらサーバ上の chat.html を実行します。chat.swf を直接実行しても構いません。ActionScript 解説
フレームアクション解説
var sl = new LoadVars();
LoadVars クラスのオブジェクトを生成しています。LoadVars クラスは Flash アプリケーションとサーバーの間で変数を転送する機能があります。送受信の流れとしては- LoadVars オブジェクトを生成する。
- send メソッドによる送信・load メソッドによる受信・sendAndLoad メソッドによる送受信を行う。
- PHP側は、print や echo などによって文字列を出力するとそれを Flash 側に渡すことができる。出力形式は GET 形式(変数名1=値1&変数名2=値2&…)で行う。
- PHP からの出力が完了したら LoadVars オブジェクトの onLoad イベントが呼び出される。
var timer = 0;
自動リロード用のタイマです。
user_txt.tabEnabled = false;
log_txt.tabEnabled = false;
オンラインユーザ一覧とチャットログが入るダイナミックテキストにタブによる移動を禁止しています。これによってタブを押したときに名前・メッセージ入力のフィールドのみを移動するようになります。
Key.addListener(msg_txt);
キーボードのキーを押したとき、msg_txt オブジェクトがその処理を受け持つようにします。これによってキーが押されたときに msg_txt オブジェクトの onKeyDown イベント、キーが離されたときに msg_txt オブジェクトの onKeyUp イベントが自動的に呼び出されるようになります。
sl.load("chat.php");
chat.php を起動し、現在までのログとユーザーを取得します。
msg_txt.onKeyDown = function() {
さきほどの Key.AddListener メソッドによって、キーが押下されたときに呼び出される関数です。
if (Key.getCode() == Key.ENTER) {
押されたキーが Enter の場合、以下のメッセージ送信処理を行います。
if (name_txt.length == 0) name_txt.text = "名無しさん";
名前を書かれていなければデフォルトの名前をセットします。
sl.name = name_txt.text;
sl.msg = msg_txt.text;
LoadVars オブジェクトに変数を設定すると、自動的に POST 変数としてサーバに送られます。ここでは名前とメッセージをテキストフィールドから受け取ってセットしています。
sl.sendAndLoad("chat.php?rn=" + Math.random(), sl);
chat.php に対してデータを送受信しています。上記でセットした変数が PHP の POST 変数として送られ、受信時には第2引数の LoadVars オブジェクトに戻り値がセットされ onLoad イベントが呼び出されます。ここで URL にランダム値を追加しているのは、同じ URL だとキャッシュのデータを引っ張ってきて更新されない場合があるためです。
sl.onLoad = function() {
PHP からデータを受信したときの処理です。
log_txt.text = this.log;
user_txt.text = this.user;
ユーザー一覧とチャットログに、PHPから受信したデータを入れています。ここでの this とは自分自身、つまり sl オブジェクトのことです。
log_txt.scroll = log_txt.maxscroll;
チャットログのスクロール値を最大にしています。これによってログの一番下までスクロールされます。
timer = 0;
リロードタイマをクリアしています。
onEnterFrame = function() {
if (++timer > 15 * 10) {
sl.load("chat.php?rn=" + Math.random());
}
}
毎フレーム処理はリロード用に使っています。タイマをインクリメントして、15 * 10 以上になったとき、つまりフレームレートが 15fps なので 10 秒経過したときに PHP からデータを受信します。PHPプログラムの解説
$lines = array();
$user = '';
$log = '';
$lines はログの各行が入る配列、$user はユーザー一覧、$log にはチャットログが入ります。
$fp = fopen('chat.txt', 'r+');
flock($fp, LOCK_EX);
ログファイルを開いてロックをかけます。
for (;;) {
$line = fgets($fp);
if (!$line) break;
array_push($lines, $line);
}
ログファイルの各行を $lines 配列に代入しています。
$time = time();
現在時刻(タイムスタンプ)を保存します。
if ($_POST['msg']) array_push($lines, "{$_POST['name']}\t{$_POST['msg']}\t$time\n");
メッセージがあれば名前・メッセージ・現在時刻をタブ区切りで配列 $lines の最後に追加します。
if (count($lines) > 50) array_shift($lines);
ログが50件以上ならば先頭の1件を削除して50件にします。
rewind($fp);
ftruncate($fp, 0);
ファイルポインタを先頭に巻き戻してファイルサイズを0にします。
foreach ($lines as $l) fputs($fp, $l);
新しいログを書き込みます。
fclose($fp);
ファイルを閉じます。同時にロックも解除されます。
foreach ($lines as $l) {
画面用のログ生成用に配列を一行ずつループします。
list($n, $m, $t) = explode("\t", $l);
タブ区切りのデータから名前・メッセージ・書き込み時刻を取得します。
$t = rtrim($t);
最後に改行が入っているので、それを削除します。
if ($time - $t < 180) {
if (!strstr($user, $n)) $user .= "$n\n";
}
ユーザー一覧に名前を追加します。まず現在時刻から書き込み時刻を引いて、それが 180 つまり 3 分未満だったらオンラインユーザーと見なします。次に strstr 関数にて既に同じ名前のユーザーがいる場合には追加しないようにしています。
$log .= "$n> $m(" . date("m/d H:i:s", $t) . ")\n";
ログを加工して追加しています。「名前> メッセージ(月/日 時:分:秒)」となります。
print "user=" . urlencode($user);
print "&log=" . urlencode($log);
Flash 側に GET 形式でユーザー一覧とログを送信します。特殊文字が入るのを防ぐためにURLエンコードしています。