Flex3でAMFPHPを試す
7月21日に大田区産業プラザで開催されたPHPカンファレンス2008に参加しました。一番の目玉セッションはパネルディスカッションだったと思うのですが、各言語ユーザの代表が集結してトークする様子で会場は大いに盛り上がりました。また、PHPという言語やコミュニティは他の言語のユーザからはどういう風に見えるのか、ということを聞けるまたとないチャンスでした。
さて、そのパネルディスカッション(CodeZineによるレポート)でパネラーの方がActionScriptを推奨していたのに影響されたのか、最近Flex/ActionScript3を調べています。今回は、PHPアプリケーションとFlashの間でメッセージのやり取りを簡単にする、AMFPHPについて調べましたのでご紹介します。
- AMFPHPとはなにか
- AMFPHPのインストール
- Gateway.php - Flashからのリクエストを受け取る
- StatusService.php - 実際にデータ処理、Flash側へ提供するサービス
- Status.mxml - フロントエンドで、データをリクエストし、受け取って表示する
- まとめ
AMFPHPとはなにか
まずAMFとは、Actionscript Message Formatのことです。どういった技術なのかについては、実はまだ勉強中なのでうまく説明できません。AMFPHPはサーバ側のライブラリであり、これを使うとFlashとPHPアプリケーションとのデータのやりとりが簡単にできるようになります。
AMFPHPのインストール
AMFPHPをDebian GNU/Linuxにインストールします。インストール先は、"/usr/local/lib/php5/amfphp"にしました。(単に取得したアーカイブを展開するだけです)
% sudo wget 'http://downloads.sourceforge.net/amfphp/amfphp-1.9.beta.20070513.zip?modtime=1190672171&big_mirror=0'
% cd /usr/local/lib/
% sudo mkdir php5
% cd php5
% sudo unzip /usr/local/src/amfphp-1.9.beta.20070513.zip
Gateway.php - Flashからのリクエストを受け取る
次にFlashからのリクエストを受け取って返すスクリプトを書きます。先ほどのようにインストールした場合は、サンプルスクリプトが"/usr/local/lib/php5/amfphp/gateway.php"にあって、これを参考にしながら記述します。(この例では、(ドキュメントルート)/statustest/gateway.phpに保存します)
<?php
include "/usr/local/lib/php5/amfphp/core/amf/app/Gateway.php";
$gateway = new Gateway();
$gateway->disableDebug();
//$gateway->setCharsetHandler("none", "ISO-8859-1", "ISO-8859-1");
//Flashとやりとりするクラスのあるディレクトリ
$gateway->setClassPath("./services/");
//zlibが有効ならgzip圧縮を使う
$gateway->enableGzipCompression(25*1024);
$gateway->service();
?>
サンプルスクリプトを参考に記述した場合には注意すべきことがあります。現在最新版に同梱のサンプルでは文字コード変換している箇所があります(127行目の「$gateway->setCharsetHandler("utf8_decode", "ISO-8859-1", "ISO-8859-1");」がそれにあたります)が、スクリプトやDBの文字コードがUTF-8の場合はこの処理は不要のようです。このAMFPHPを試していて、5時間ほどこの文字化けに悩まされました。もし文字化けしていて、文字コードの設定は正しいと思うときには、どこかでこの処理が呼び出されていないかチェックしてみてください。参考資料:映像とその周辺: AMFPHPで文字化け
StatusService.php - 実際にデータ処理、Flash側へ提供するサービス
PHPでサーバーサイド処理をして、Flash側にデータを渡すスクリプトは以下の通りです。(この例では、(ドキュメントルート)/statustest/services/StatusService.phpに保存します)
<?php
class StatusService
{
function loadData()
{
$specs = array(
array(
"name" => "スミス",
"level" => 5,
"special" => "つめたいいき"
),
array(
"name" => "スラきち",
"level" => 10,
"special" => "リレミト"
),
array(
"name" => "ピエール",
"level" => 15,
"special" => "ベホイミ"
),
);
return $specs;
}
}
?>
シンプルな例で、単に連想配列を返すメソッドを定義しました。注意することは、ファイル名とクラス名を同じにすることです。
Status.mxml - フロントエンドで、データをリクエストし、受け取って表示する
最後に、SWFを生成するソースコードをmxmlという形式で記述します。以下のコードをコンパイルするのにFlex Builderか無償のFlex SDKが必要になります。環境の無い方はFlex Builderの試用版をインストールするかFlex 3 SDKによるFlash開発入門を参考にしてSDKをインストールしてください。(これはWindows XPにインストールしました)
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()">
<mx:Script>
<![CDATA[
import flash.net.NetConnection;
import flash.net.Responder;
import flash.net.ObjectEncoding;
[Bindable]
private var specList:Object = [];
private const GATEWAY_URL:String = "/statustest/gateway.php";
private function init():void {
var responder:Responder = new Responder(onResult, onFault);
var conn:NetConnection = getConnection();
conn.call("StatusService.loadData", responder);
}
private function onResult(result:Object):void {
specList = result;
}
private function onFault(fault:Object):void {
trace(fault);
}
private function getConnection():NetConnection {
var conn:NetConnection = new NetConnection();
conn.connect(GATEWAY_URL + "?time=" + (new Date()).getTime());
conn.objectEncoding = ObjectEncoding.AMF3;
return conn;
}
]]>
</mx:Script>
<mx:Panel layout="absolute">
<mx:DataGrid id="dataGrid" dataProvider="{specList}">
<mx:columns>
<mx:DataGridColumn headerText="なまえ" dataField="name"/>
<mx:DataGridColumn headerText="レベル" dataField="level"/>
<mx:DataGridColumn headerText="とくぎ" dataField="special"/>
</mx:columns>
</mx:DataGrid>
</mx:Panel>
</mx:Application>
こちらのコードを、"Status.mxml"という名前で保存して、コンパイルすると(コマンドラインで、mxmlc Status.mxml)Status.swfというファイルが生成されます。このファイルを"(ドキュメントルート)/statustest/Status.swf"に保存します。
スクリプトはXML形式になっていますが、今回のサンプルでは、大きく分けてActionScriptのソースコード部分と、GUIインターフェイスを定義する部分に分かれています。mx:Application要素のinitialize属性に記述したメソッドが呼び出され、initメソッドの中で読み込み処理が行われます。受け取ったデータはonResultメソッドで処理します
注目するところは、まずPHP側のクラスやメソッドをフロントエンドのスクリプトから指定している所です。(conn.callメソッドの呼び出しがそうです)また、受け取ったデータをデバッグ表示するとわかりますが、ちゃんとActionScriptのオブジェクトになっています。
これで、ブラウザから見られるようになります。http://[yourhost]/statustest/Status.swfにアクセスすると、以下のようなテーブルが表示されると思います。
まとめ
AMFPHPを使って、フロントエンドのFlashプログラムとバックエンドのPHPの間で容易にデータのやり取りができるようになるサンプルを紹介しました。以前JSONを使ったAjax通信について紹介しましたが、AMFPHPはこのJSONで言うところのjson_encode(), json_decode()関数と同じような仕事をやっているといえます。
参考文献
- AMFPHPを試してみました : アシアルブログ
- 全体的なプログラム構造などはこちらで勉強しました。私のActionScriptのコードはこちらのコードを簡素にしたものです。
- Adobe - デベロッパーセンター : JSONを使用したFlexおよびPHP間のデータ送信
- JSONは今回とりあげませんでしたが、テーブルの定義はこちらも参考にしました。
- Flex の Bindable 入門 - てっく煮ブログ
- [Bindable]とソースコードにありますが、その分かりやすい説明はこちら
- mxmlc コンパイラのメタデータタグを利用する - [Bindable] 篇 - 川o・-・)<2nd life
- [Bindable]その2 きちんと把握すると、ソース記述が減るそうです。