2009年3月3日 星期二

AMFPHP簡介

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

  1. include “../flashservices/app/Gateway.php”;

  2. $gateway = new Gateway();

  3. $gateway->setLooseMode(true);

  4. $gateway->setCharsetHandler(“iconv”, “UTF-8″, “UTF-8″);

  5. $gateway->setWebServiceHandler(‘php5′);

  6. $gateway->setBaseClassPath(“services/”);

  7. $gateway->service();

  8. ?>

這裏新手最常錯的地方就是第一行,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的設定為預設值。

所以總之照範例裏的設定直接套用就一定不會錯 :P

最後看一下第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

  1. class Hello

  2. {

  3. //constructor

  4. function Hello()

  5. {

  6. $this->methodTable = array(

  7. “sayHello” => array(

  8. “description” => “Return hello message to client”,

  9. “access” => “remote”,

  10. “arguments” => array(“”)

  11. ),

  12. );

  13. }

  14. //remote method

  15. function sayHello($msg)

  16. {

  17. return “Amfphp welcomes you: “ . $msg . ” current time_” . time();

  18. }

  19. }

  20. ?>

如果你有撰寫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

  1. /*

  2. @author: jeremy@richtechmedia.com

  3. @website: http://ria.richtechmedia.com

  4. released under CC 2.5.

  5. */

  6. //remoting related classes

  7. import mx.remoting.Service;

  8. import mx.remoting.PendingCall;

  9. import mx.remoting.RecordSet;

  10. import mx.remoting.debug.NetDebug;

  11. import mx.rpc.RelayResponder;

  12. import mx.rpc.ResultEvent;

  13. import mx.rpc.FaultEvent;

  14. //start debugging so we can see debug info in NCD.

  15. NetDebug.initialize();

  16. //gateway settings

  17. var gateway:String = “http://localhost/hello/gateway.php”;

  18. respGeneral = new RelayResponder(this, “resultReceived”, “resultFailure”);

  19. _service = new Service(gateway, null, “Hello”, null, respGeneral);

  20. //callback when result was returned from server

  21. function resultReceived(re:ResultEvent):Void{

  22. trace(“message from server> “ + re.result);

  23. //php returns time in seconds, but flash Date class needs ms hence * 1000

  24. var tmp = re.result.split(“_”)[1]*1000;

  25. trace(“server time> “ + new Date(tmp));

  26. };

  27. //send message to server

  28. btnSend.clickHandler = function(){

  29. var pc:PendingCall = _service.sayHello(inputText.text);

  30. }

一開始我們先將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的認証等,但這些都是後話,在之後的範例中都會解釋。

沒有留言:

張貼留言