flashとのAMF通信用CakePHPコンポーネント
こんにちは、中川です。
以前、「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
を作成します。
<?php
//sabreamf_ini.php
define('SABREAMF_PATH', dirname(__FILE__));
set_include_path(SABREAMF_PATH . PATH_SEPARATOR . get_include_path());
?>
あとは今回作成したコンポーネント、sabre_amf.php を
/PROJECT_DIR/app/controllers/components/sabre_amf.php
に設置します。
<?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");
とすれば、SabreAMFを利用してFlashとAMFでやりとりができるようになります。
以下、簡単な、文字列と、配列のやり取りのサンプル用Controllerです。
<?php
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