flashとのAMF通信用CakePHPコンポーネント
こんにちは、中川です。
以前、「AMFPHPを試してみました」でphpとFlashの通信を試してみましたが、
今回はCakePHPを使ったFlashとAMFでのやり取りする方法を考えてみました。
CakePHPでAMF通信ができるものを探してみたところ、
「CakeAMFPHP」、
「CakeAMF」、
「CakeSWXPHP」
など、いろいろ見つかりました。
一通り試してみましたが、設置が面倒であったりうまく動かなかったり
(私のやり方が悪いと思いますが、)どうもしっくりきませんでした。
もっとCakePHPから使いやすそうなものがないか探してみたところ、
「SabreAMF」というライブラリを見つけました。
これを通常の使用方法で試したところ、非常に簡単にやり取りができましたので、
CakePHPからも使いやすいようにCakePHP用のコンポーネントを作ってみました。
※動作イメージ
構成は以下のようになります。
まず、SabreAMFの最新ライブラリ(今回はSabreAMF-1.1.187)を http://code.google.com/p/sabreamf/downloads/list から
ダウンロードして、解凍しSabreAMFに改名して、
そして、パス設定用のファイル
これで準備完了です。
AMFを使用したいControllerで、
以下、簡単な、文字列と、配列のやり取りのサンプル用Controllerです。
あとは、このコントローラにFlashからリクエストのサンプルです。
■RemoteTest.mxml(RemoteTest.swf)
上記サンプルでは、RemoteObjectを使用していますが、
NetConnectionを使った場合は以下のような感じで通信できると思います。
(以前のAMFPHPの記事も参照)
※しっかりした、動作確認はできておりません。
使用される場合は自己責任でご自由にお使いください。
-----------------------------------------------
最近CakePHPの人気はすごいですねー。今週水曜CakePHPの勉強会ですが、
申し込みに間に合わず、満員で参加できませんでしたorz
いきたかったなぁ~。。。
以前、「AMFPHPを試してみました」でphpとFlashの通信を試してみましたが、
今回はCakePHPを使ったFlashとAMFでのやり取りする方法を考えてみました。
CakePHPでAMF通信ができるものを探してみたところ、
「CakeAMFPHP」、
「CakeAMF」、
「CakeSWXPHP」
など、いろいろ見つかりました。
一通り試してみましたが、設置が面倒であったりうまく動かなかったり
(私のやり方が悪いと思いますが、)どうもしっくりきませんでした。
もっとCakePHPから使いやすそうなものがないか探してみたところ、
「SabreAMF」というライブラリを見つけました。
これを通常の使用方法で試したところ、非常に簡単にやり取りができましたので、
CakePHPからも使いやすいようにCakePHP用のコンポーネントを作ってみました。
※動作イメージ
構成は以下のようになります。
- `--
myproject `-- app |-- controllers | |-- amfs_controller.php(サンプルファイル) | `-- components | `-- sabre_amf.php(コンポーネント) `-- vendors |-- SabreAMF(解凍した中身を配置) `-- sabreamf_ini.php(PATH設定用ファイル)
まず、SabreAMFの最新ライブラリ(今回はSabreAMF-1.1.187)を http://code.google.com/p/sabreamf/downloads/list から
ダウンロードして、解凍しSabreAMFに改名して、
- /PROJECT_DIR/app/vendors/SabreAMF
そして、パス設定用のファイル
- /PROJECT_DIR/app/vendors/sabreamf_ini.php
- //sabreamf_ini.php
- define('SABREAMF_PATH',
dirname(__FILE__)); - set_include_path(SABREAMF_PATH
. PATH_SEPARATOR . get_include_path());
- /PROJECT_DIR/app/controllers/components/sabre_amf.php
- //sabre_amf.php
- vendor("sabreamf_ini");
- vendor('SabreAMF/CallbackServer');
- $_cakeController
= null; - function
amfCallBack($service, $method, $data) { global $_cakeController; $res = null; if ($_cakeController) { if (strpos($method, "_") !== 0) { // _(アンダーバー)で始まるmethodはエラー。 $_cakeController->amfData = $data; if (method_exists($_cakeController, $method)) { $res = $_cakeController->{$method}(); } else { $res = "not found action."; } } else { $res = "invalid method name."; } } else { $res = "not found controller."; } return $res; - }
- class
SabreAmfComponent extends Object { function initialize(&$controller) { global $_cakeController; $_cakeController = $controller; $controller->isAmf = true; // default true } function startup(&$controller) { if ($controller->isAmf) { Configure::write('debug', 0); $controller->autoRender = false; $server = new SabreAMF_CallbackServer(); $server->onInvokeService = 'amfCallBack'; $server->exec(); exit; //ここでexitしてるので、amf の 場合はほかのactionは呼べないはず。。。 } } function beforeRender(&$controller) { if ($controller->isAmf) { exit; // 念のため } } - }
これで準備完了です。
AMFを使用したいControllerで、
- var
$components = array("SabreAmf");
以下、簡単な、文字列と、配列のやり取りのサンプル用Controllerです。
- class
AmfsController extends AppController { var $name = 'Amfs'; var $uses = array(); var $components = array("SabreAmf"); function beforeFilter() { // ここでamf出力ではないactionを設定できる。 // 全部amf出力の場合は何も設定いらない。 // この場合は「normal」のみ通常アクセスできる。 // ほかのactionは、URLからは実行されないはず。。。 if ($this->action == "normal") { $this->isAmf = false; Configure::write('debug', 2); $this->autoRender = true; } } // indexアクションは通常出力に使わないほうがいい。 // beforeFilterで除外すると、初期アクセスがamfから指定ない場合、 // リモートで呼び出されたときにエラーでちゃう function index() { return "index"; } //これは通常表示できるアクション function normal() { $this->set("hoge", date("Y-m-d H:i:s")); } //文字列返却 function getstr() { $testname = $this->amfData[0]; // flashから送られてきた値はamfDataにある。しかし、キーが消えてるよ。。。 return date("Y-m-d H:i:s") . " こんにちは " . $testname; //各action で return した値が flashに返る。 } //配列返却 function getarr() { $res_list = array(); for($i = 0; $i < 10; $i++) { $res = array( "col1" => $i, "col2" => rand(1, 1000), ); $res_list[] = $res; } $this->log(print_R($res_list, true), LOG_ERROR); return $res_list; } - }
あとは、このコントローラにFlashからリクエストのサンプルです。
■RemoteTest.mxml(RemoteTest.swf)
- <?xml
version="1.0" encoding="utf-8"?> - <mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"> <mx:Script> <![CDATA[ import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.controls.Alert; import mx.utils.ArrayUtil; [Bindable] private var myDataItem:Array = []; private function resultHandler(evt:ResultEvent):void { myDataItem = ArrayUtil.toArray(evt.result); } private function faultHandler(evt:FaultEvent):void { Alert.show("Fault: " + evt.fault + " Msg: " + evt.message); } ]]> </mx:Script> <!-- remoting-config.xmlをちゃんと設定したほうがいいのかな? このサンプルでは、xmlを用意しないで、endpoint指定でやってます。 endpoint="{'http://{server.name}:{server.port}/amfs/'}" と書けば、 flash設置サーバの/amfs/と通信します。 以下のようにendpoint(cakeのcontroller呼び出し用URL)さえ指定しておけば source は今回の場合は適当でいいです。というのも、sevice名として サーバで受け取りますが、endpointのcakeのcontrollerの メソッドしか呼べないようにしているので送信しているが使っていない。 また、destinationも適当でいいですが指定しないとエラーでます。 --> <!-- 文字列読み込み例 --> <mx:RemoteObject id="ro" endpoint="{'http://{server.name}:{server.port}/amfs/'}" destination="MyAmfs" source="Amfs" result="myLabel.text = event.result.toString()" fault="faultHandler(event)"> <mx:method name="getstr"> <mx:arguments> <testname>hoge</testname> </mx:arguments> </mx:method> </mx:RemoteObject> <mx:Label text="string_sample" id="myLabel" /> <mx:Button label="string load test" click="ro.getstr.send()" x="24" y="42"/> <!-- ro.●●.send() でcake側のアクションを呼べる --> <mx:Spacer height="2" width="200"/> <!-- 配列読み込み例 --> <mx:RemoteObject id="ro2" endpoint="{'http://{server.name}:{server.port}/amfs/'}" destination="MyAmfs" source="Amfs" result="resultHandler(event)" fault="faultHandler(event)"> </mx:RemoteObject> <mx:Button label="array load test" click="ro2.getarr.send()" x="24" y="42"/> <mx:DataGrid id="myData" dataProvider="{myDataItem}"> <mx:columns> <mx:DataGridColumn headerText="列 1" dataField="col1"/> <mx:DataGridColumn headerText="列 2" dataField="col2"/> </mx:columns> </mx:DataGrid> - </mx:Application>
上記サンプルでは、RemoteObjectを使用していますが、
NetConnectionを使った場合は以下のような感じで通信できると思います。
(以前のAMFPHPの記事も参照)
- var
con:NetConnection = new NetConnection(); - con.connect(GATEWAY_URL);
- con.objectEncoding
= ObjectEncoding.AMF3; - con.call("Amfs.getstr",
new Responder(resultHandler, faultHandler));
※しっかりした、動作確認はできておりません。
使用される場合は自己責任でご自由にお使いください。
-----------------------------------------------
最近CakePHPの人気はすごいですねー。今週水曜CakePHPの勉強会ですが、
申し込みに間に合わず、満員で参加できませんでしたorz
いきたかったなぁ~。。。
コメント
コメントフォーム
トラックバックURI
-
- [CakePHP] AIRからSabreAMFを利用してCakePHPに通信する from 私的WEBサイト制作日誌
- AirのSWFファイルからPHPが動いているサーバーに接続する為には、AMFと...
2008年11月24日 20:31
最近の記事
システム開発エンジニア募集! [2012年02月03日 : 小林有佳]
OpenVPNで細々便利な設定 [2012年01月31日 : 門脇優児]
【iOS】Viewの開発・デバッグに役立つ色々 [2012年01月23日 : 中川善樹]
PHPDocumentorの利用方法まとめ [2012年01月19日 : 笹亀弘]
Google Chart Toolsを使ってサイトマップを描こう! [2011年12月21日 : 志田仁美]
stumpwm設定v2 [2011年12月19日 : 門脇優児]
Mashup Awards 7の授賞式が行われました [2011年12月16日 : 中川善樹]
社員旅行に行きました [2011年12月12日 : 大橋寛子]
iCloud風のアイコンを作成する(Fireworks) [2011年12月07日 : 和田記光]
iScroll4でネイティブに近いスマホ向けHTMLページを作成する [2011年12月02日 : 松田惇]













このコード公開してくれればありがたいのに・・・。
このページコードを参考にsabreAMFとCakePHPでやってみましたがうまくいきませんでした。
以下環境です。
━━━━━━━━━━━━━━
SabreAMF-1.2.203.tgz
CakePHP1.2 RC3
Flex Buider 3
AIR 1.5
━━━━━━━━━━━━━━
SWFはデータ送信時、内部的に初回だけ2回POSTするらしく、
sableAMFのCallbackServer.phpのexecメソッドで
振り分け処理を行っているようです。
1回目:CommandMessage(PING)
2回目:RemotingMessage(データ)
1回目のCommandMessageは受け取ってデータを返すところまで、
PHP側にログを出力させて確認できました。
ただ、apacheのログを見ても、2回目のPOSTが走らないようです。
1回目のPINGでの返信データがおかしいんですかね??
何か情報をお持ちでしたら教えて下さいm(_ _)m
なんだかんだ手こずったのですが、ソースコードをコピペする際に、phpタグの前にスペースが混入してしまっていたため、失敗してました。
気づくまでに丸2日かかりました。。情けない。。
ご存知のとおり、CakePHP1.2の場合は、vendorタグをApp::importに書き換えるとうまくいきました。
How to deal with authentication?