アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

AMFPHPを試してみました

AMFPHPを使ってPHPFlashでAMF形式での通信を試してみました。

AMF とは、ActionScript Message Formatと呼ばれる仕様非公開のバイナリフォーマットです。
テキストベースの形式と比べ軽量で、高速に扱うことができるそうです。
AMFPHPでは、AMF形式でのやり取りをサポートし、簡単にFlashからPHPのメソッドを呼び出すことができ、
また、PHPFlashでやり取りするデータの変換も自動で行ってくれるので、非常に簡単にやり取りができます。


Q.クリスマス何してました?


※初めて使ったので、おかしな点や、もっとスマートな書き方があると思いますので注意願います。

まず、AMFPHPライブラリを http://amfphp.org/ からダウンロードし、/path/to/amfphpに配置します。
今回使用したバージョンは、amfphp-1.9.beta.20070513 です。


次にflashから、送信先のファイルとなるamftest_gateway.phpを作成します。

■/var/www/public_html/amftest_gateway.php


<?php
$AMFPHP_DIR =  "/path/to/amfphp";	//AMFPHPディレクトリへのpath
include $AMFPHP_DIR . "/core/amf/app/Gateway.php";

$gateway = new Gateway();
$gateway->disableDebug();
$gateway->setClassPath($AMFPHP_DIR . "/services/");	//使用するクラスの場所
//$gateway->setCharsetHandler("utf8_decode", "ISO-8859-1", "ISO-8859-1");
$gateway->enableGzipCompression(25*1024);
$gateway->service();
?>


そして、/path/to/amfphp/servicesフォルダを作成し、使用するクラスを設置します。
今回は、TestService.phpファイルをひとつ設置しました。

■/path/to/amfphp/services/TestService.php


<?php

define("LOG_FILE", "/path/to/log.csv");//書込み権限を設定

class TestService{
    var $methodTable;
    
    function TestService(){
        /* //なくても動いてる。。。
        $this->methodTable = array(
        		"loadData" => array("description" => "amfphp test data load",
                               "access" 		 => "remote",
                               "arguments"   => null 
                              ),
            "writeData" => array("description" => "amfphp test data load",
                               "access" 		 => "remote",
                               "arguments"   => array("name_str", "body_str") 
                              ),
                        	);
        */
    }
    
   	/**
   	 *	ログファイル読み込み配列で返却
   	 **/
    function loadData() {
    	$fp = fopen(LOG_FILE, "r");
    	$res_list = array();
    	while(!feof($fp)) {
    		$buf = fgets($fp, 4096);
	    	$d = explode(",", $buf);
    		$r_data = array(
    			"name" => $d[0],
    			"body" => $d[1]
    		);
    		$res_list[] = $r_data;
    	}
    	array_pop($res_list);//空データ削除
    	return array_reverse($res_list);	//新しい順に返却
    }
		
		/**
		 * 	ログファイルに書込み(※CSV形式、カンマ除去)
		 **/
    function writeData($name_str = "", $body_str = ""){
	    if ($name_str  & & $body_str) {
	        $log = str_replace(",", "", $name_str) . "," . str_replace(",", "", $body_str) . "\n";	//カンマ削除
	        $fp = fopen(LOG_FILE, "a");
	        fputs($fp, $log);
	        fclose($fp);
	    }
        $res_list = $this->loadData();
        return $res_list;
    }
}

?>


あとは、flash側から、amftest_gateway.phpへ使用するサービスのクラス名と、メソッドを指定することで、
flashからPHPのメソッドを実行できます。


■main.mxml(main.swf)


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="top" backgroundColor="white" creationComplete="init();">
	
	<mx:Script>
		<![CDATA[
		import mx.controls.Alert;
		import flash.net.NetConnection;
		import flash.net.ObjectEncoding;
		import flash.net.Responder;
		
		[Bindable]
		public var dataList:Array = [];		//   [{"name":"hoge", "body": "foo"}] 形式
		
		private const GATEWAY_URL:String = "/sample/323/amftest_gateway.php";
		
		/**
		 *  初期データ読み込み
		 */
		private function init():void {
			var responder:Responder = new Responder(onResult, onFault);
			var con:NetConnection = getCon();
			con.call("TestService.loadData", responder);
		}
		
		/**
		 * 	データ送信
		 * */
		private function sendMessage():void {
			var nametxt:String = nameText.text;
			var bodytxt:String = bodyText.text;
			nameText.text = "";
			bodyText.text = "";
			
			var responder:Responder = new Responder(onResult, onFault);
			var con:NetConnection = getCon();
			con.call("TestService.writeData", responder, nametxt, bodytxt);
		}
		
		/**
		 * 	コネクション初期化
		 **/
		private function getCon():NetConnection {
			var time:Number = (new Date()).getTime();
			var con:NetConnection = new NetConnection();
			con.connect(GATEWAY_URL + "?time=" + time);
			con.objectEncoding = ObjectEncoding.AMF3;
			return con;
		}
		
		/**
		 * 	成功
		 **/
		private function onResult(etc:*):void {
			if (typeof etc == "object") {
				dataList = etc;
			} else {
				Alert.show("Error-2");
			}
		}
		
		/**
		 * 	失敗
		 **/
		private function onFault(etc:*):void {
			Alert.show("Error-1");
		}
		
		]]>
	</mx:Script>
	
	<mx:ApplicationControlBar dock="true">
		<mx:Label data="名前:" />
		<mx:TextInput id="nameText" width="10%" />
		<mx:Label data="内容:" />
		<mx:TextInput id="bodyText" width="80%" />
		<mx:Button id="sendButton" label="送信" click="sendMessage();" />		
	</mx:ApplicationControlBar>
	
	<mx:DataGrid id="dataGrid" dataProvider="{dataList}" width="100%" height="100%">
		<mx:columns>
			<mx:DataGridColumn dataField="name" headerText="名前" width="100" />
			<mx:DataGridColumn dataField="body" headerText="内容" />
		</mx:columns>
	</mx:DataGrid>
	
</mx:Application>


データの変換等をすべてAMFPHPで処理してくれるので、簡単にPHPFLASHでやり取りができます。