Amfphp最早是由Justin Watkins所發起並負責撰寫第一版大部份的程式碼,經過三年發展後去年由Patrick Mineault接手,不但改良了大部份的程式碼,同時也補齊了許多重要的功能,例如本系列第二篇要介紹的 pageable recordset。
Amfphp是一個完全由php寫成的server端模組,最大的特色在於完全不用安裝,任何hosting 主機只要能跑php就能執行flash remoting,再加上php原本就有廣大的使用者基礎,因此一推出後很快就獲得玩家們的接受。
如果你想要瞭解amfphp的最新方展,可前往 amfphp wiki 一探究竟,如果你有使用上的疑問,最好的解答就在amfphp mailing list 或是 forum 。
◆下載amfphp
目前amfphp最新版為 v1.0 milestone 2,據patrick的說這應該是正式發表前最後一個beta版,所以穩定性應該相當不錯才是。
下載位址
◆安裝amfphp
檔案抓回來後解壓縮,應該會得到下圖的結構:
其中flashservices就是amfphp的核心模組,只要將它上傳到網頁的根目錄下即可。本文是以windows + apache 2為例,因此放置位為:
C:\Program Files\Apache Group\Apache2\htdocs\flashservices
其中 htdocs即是apache預設的網頁根目錄,如果你的位置不同請適當修改。
放好 flashservices後基本核心就已完成,但這不代表就可以開始使用,我們還要為每個專案建立專屬的資料夾來放置其它必備的檔案。
◆第一個程式:hello world
這裏我們用一個實際的hello world範例來示範如何讓flash 與 php透過amfphp進行溝通。
首先我們在剛才的網頁根目錄下(htdocs)建一個專案資料夾,名稱為 hello,完整路徑為:
C:\Program Files\Apache Group\Apache2\htdocs\hello
然後請下載本文的範例檔案zip檔,將裏面的東西全部解壓縮到hello資料夾內,此時資料夾的內容應該如下圖:
◆ Amfphp gateway的設定
接者我們就仔細看看裏面有些什麼東西,首先我們來看 gateway.php,程式碼如下:
PLAIN TEXT
-
-
include “../flashservices/app/Gateway.php”;
-
$gateway = new Gateway();
-
$gateway->setLooseMode(true);
-
$gateway->setCharsetHandler(“iconv”, “UTF-8″, “UTF-8″);
-
$gateway->setWebServiceHandler(‘php5′);
-
$gateway->setBaseClassPath(“services/”);
-
$gateway->service();
-
?>
這裏新手最常錯的地方就是第一行,include的設定。一般由於 flashservices核心模組都是放置於web server的根目錄,因此每個專案的子資料夾只要用相對路徑 .. 就可以存取到。但如果你的flashservices路徑不一樣,這裏就要做適當的修改,例如在我使用的hosting主機上(使用linux系統),這 個路徑就可能變成:
/home/userrname/website.url/user/apache/htdoc/flashservices
總之這裏請小心確認路徑無誤。
接者第5行的設定也很重要,這裏主要是在設定php該用何種語系處理資料,它的標準格式如下:
setCharsetHandler(string mode, string phpCharset, string sqlCharset)
第一個參數是設定要使用何種方式來重新編碼傳輸的資料,如果是php5的話則可以放使用iconv,這是內建的模組。
第二個參數是設定系統預定的文字編碼方式,如果要用中文的話就改成 utf-8。
第三個參數是設定該如何處理sql query result,也就是recordset的文字編碼,同樣的要用中文請設定成 utf-8。
本來這裏還有第四個參數,是設定 wsCharset (web service charset),但從ms1版本開始這個參數已被預設為utf-8,將來不論是使用SoapClient或 nusoap都會自動讀取 phpCharset的設定為預設值。
所以總之照範例裏的設定直接套用就一定不會錯
最後看一下第7行,這裏是設定server端的程式位置,一般也就是business logic的所在地,或是business delegate的class位置(如果你希望將server端的logic儘量隱藏起來只透過單一管道供flash呼叫的話,這裏就是下手的好地方), 預設值是server,這也就是為何解壓縮範例檔後會出現一個同名資料夾的原因。
◆php class的內容
接者我們看一下service資料夾內的Hello.php,這個就是server端的程式,它的地位相當於coldfusion 裏的component(CFC)或java裏的java bean。
它的程式碼如下:
PLAIN TEXT
-
-
class Hello
-
{
-
//constructor
-
function Hello()
-
{
-
$this->methodTable = array(
-
“sayHello” => array(
-
“description” => “Return hello message to client”,
-
“access” => “remote”,
-
“arguments” => array(“”)
-
),
-
);
-
}
-
-
//remote method
-
function sayHello($msg)
-
{
-
return “Amfphp welcomes you: “ . $msg . ” current time_” . time();
-
-
}
-
}
-
?>
如果你有撰寫php class的經驗,應該馬上會發現這個Hello 就是一個標準的php class檔,透過class keyword來宣告class的啟始,並且在constructor裏有一個method table描述整個class要供外界操作的method。
注意這個method table裏還有許多關鍵字可用,在未來的教學文章裏會依序介紹。這裏我們只用到description, access, arguments三樣。其中access一定要設定成remote,這個method才能為外界所存取,不然就會出現錯誤訊息。
第17行開始我們寫了一個sayHello($msg) ,它會接收遠端傳來的一個參數$msg,然後我們將這個$msg加料後再傳回去。加料的部份是19行最後的time(),我們將目前server的時間傳回flash。
◆flash端程式
接者我們看一下flash端的程式。首先請注意我在timeline的第1格用include的方式將程式碼加進去,這樣我就不用在flash 裏可憐的寫程式碼,而可以用 eclipse或primailscirpt等超強無敵編輯器快樂的寫作;所以你要找程式碼的話,直接打開code.as這個檔案即可。
Code.as的內容:
PLAIN TEXT
-
/*
-
@author: jeremy@richtechmedia.com
-
@website: http://ria.richtechmedia.com
-
released under CC 2.5.
-
*/
-
-
//remoting related classes
-
import mx.remoting.Service;
-
import mx.remoting.PendingCall;
-
import mx.remoting.RecordSet;
-
import mx.remoting.debug.NetDebug;
-
import mx.rpc.RelayResponder;
-
import mx.rpc.ResultEvent;
-
import mx.rpc.FaultEvent;
-
-
//start debugging so we can see debug info in NCD.
-
NetDebug.initialize();
-
-
//gateway settings
-
var gateway:String = “http://localhost/hello/gateway.php”;
-
respGeneral = new RelayResponder(this, “resultReceived”, “resultFailure”);
-
_service = new Service(gateway, null, “Hello”, null, respGeneral);
-
-
//callback when result was returned from server
-
function resultReceived(re:ResultEvent):Void{
-
trace(“message from server> “ + re.result);
-
//php returns time in seconds, but flash Date class needs ms hence * 1000
-
var tmp = re.result.split(“_”)[1]*1000;
-
trace(“server time> “ + new Date(tmp));
-
};
-
-
//send message to server
-
btnSend.clickHandler = function(){
-
var pc:PendingCall = _service.sayHello(inputText.text);
-
}
一開始我們先將flash remoting需要的class都import進來,這裏要注意的是,flash remoting需要另外下載與安裝,下載的方式有兩種:
1、 下載flash remoting components (v2)並裝入flash
2、 下載flash remoting sources並解壓縮到 mx目錄下。
第一種方式比較簡單,只要安裝mxp即可將remoting元件裝入flash,日後使用時只要直接拖放這個元件到畫面上即可。第二種方式則是直接 取回remoting classes並放入flash預設的mx路徑中,這樣做的好處有很多,例如可以三不五時修改一些地方以符合自已的需求,或是將來想用FAME開發時,也 可以讓MTASC正確的編譯。
這裏我假設你已經裝好flash remoting 元件的版本,在components裏也可以看到 flash remoting connector這個元件。
第17行我們啟動NetDebug這個偵錯程式,它會將所有的傳輸交易訊息都顯示在NetConnection Debugger(開啟方式 Window > Other Panel > NetConnection Debugger) 裏,方便除錯,它是工程師的好朋友,實在不能一天沒有它…
第20行開始我們設定了將來連線的路徑,注意裏面的hello就是當初我們在htdocs裏建的hello資料夾,而gateway.php就是前一節所介紹的php檔案。
第21行我們設定了一個general responder,也就是一個catch-all的回應物件,只要server端有回傳訊息,就由這裏設定的兩支function去承接與處理。當然 remoting處理回傳訊息的方式還有很多種,這裏因為是hello world級的範例就先按下不表。
第22行我們建立了一個 _service object,這是模擬遠端class的一個物件,請特別注意第三個參數 Hello,它是指 C:\Program Files\Apache Group\Apache2\htdocs\hello\services\Hello.php 也就是前一節介紹過的php class。
經過這三行的設定,我們就完成flash內的連線設定,接下來就可以開始呼叫遠端的method囉!
我們先跳到第33行,這裏我們設定了一個按鈕,當按下時它會執行
var pc:PendingCall = _service.sayHello(inputText.text);
也就是透過先前建立的 _serive物件去呼叫server端的sayHello method, 並且將文字框內輸入的內容傳回去。
這邊另外要注意的是PendingCall的使用,由於我們可能同時對server發生多個request,但遠端連線回應的速度通常不是即時的, 因此需要PendingCall來個別指定每個request的callback function,將來一堆訊息傳回時才能正確的處理。
最後我們回到第25行,這個function就是負責接收並處理server回傳資料的地方。首先我們在第26行將server傳回的訊息直接trace出來,注意這裏要使用 re.result才能存取到正確的訊息,這是常見的錯誤之一。
接者第28、29行則是將php傳回的date string轉換回flash的Date格式,由於php是以 string的方式處理時間格式,因此這裏我們得辛苦點自已將它再轉回Date object。
到這裏程式碼就告一個段落,我們來執行看看吧!
這是程式執行的畫面,我們輸入一些文字後按下send.
這是flash將輸入文字傳回php的畫面,請注意參數部份正是我們輸入的文字
這是php回傳訊息的畫面,訊息的尾端已加上系統的時間
◆ending
這個例子中我們很簡單的跑了一遍flash + amfphp + php 的執行範例,從flash傳一個文字串回php,並從php傳一個date物件回來。
在真實案例中面對的情況往往會比這個複雜許多,例如至少會跟database互動撈資料互傳,或是進行authentication的認証等,但這些都是後話,在之後的範例中都會解釋。