◆flash remoting是什麼?
Flash remoting是一種連接flash client 與 server端的技術,它的功用就像是 web service, xml, loadVars一般,可以在兩者之間交換資料,達到動態置換內容的目地。
Flash remoting特別的地方在於它採用macromedia獨家的AMF(Action Message Format),這是一種 binary format的資料型態,透過 AMF over HTTP的方式將flash端資料編碼後傳回server,server端的remoting adaptor接收到資料後則會解碼回正確的native物件,交給正確的程式處理。
AMF除了用於Flash remoting外,也廣泛的用於 Local Connection 與 Flash communication server,它最大的特色在於可直接將flash native object,例如Object, Array, Date, XML,傳回server端,並且在server端自動進行轉譯成適當的物件,例如flash 的Array傳回PHP時就會自動轉換為 Associative Array;這個特色對開發者最大的好處在於不需要再人工處理serialization 與 deserialization的繁複工作,不但精確度更高,同時開發也更省時間。
由於AMF是binary format並且編碼時經過高度壓縮,因此非常適合用來傳遞大量的資料,根據flashorb網站的測試(主要針對web service與flash remoting),當資料量越大時,flash remoting的傳輸效能就越高,遠遠超過web service的表現,因此同樣的道理也可得知xml, loadVars, loadVariables 等使用plaine text format的傳輸方式自然也無可比擬。
至於在server端,目前macromedia官方支援的平台有三種,分別是 Java Coldfusion(但實際上Coldfusion應該只算是java的subset,它是一種 scripting tag library)與.NET,但由於AMF格式已被玩家反組譯成功,因此很快的就在Open Source圈出現各種「民間版」的remoting替代方案,其中比較有名的是:
-AMFPHP: 這是php版的remoting
-OPENAMF: java版的remoting
-Flap: Perl 與Python版的remoting
-FlashORB: 商業版的remoting替代方案,目前支援java與.net
相關閱讀:
十個採用remoting的理由:
◆amfphp是平麼?
本文主要介紹的是php平台上的remoting方案,也就是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,程式碼如下:
PHP:
-
<?php
-
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。
它的程式碼如下:
PHP:
-
<?
-
class Hello
-
{
-
//constructor
-
function Hello()
-
{
-
$this->
methodTable =
array(
-
-
"description" => "Return hello message to client",
-
"access" => "remote",
-
-
),
-
);
-
}
-
-
//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的內容:
Actionscript:
-
/*
-
@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的認証等,但這些都是後話,在之後的範例中都會解釋。
本文的範例檔案下載。
ps.如果你遇到任何執行上的問題歡迎隨時發問,但請提供必要的背景資料給我,例如使用的作業系統、web server, php版本, amfphp版本以及錯誤訊息、代號或程式碼行數,這樣我能更快瞭解你的問題所在也才能提供正確的答案。
| by admin
◆ 前言
資料分頁(pageable recordset)一直是網頁應用程式中非常重要的一項技巧,通常工程師不會將大量的資料一次傳回給client,而是將資料先預存在server端,等client需要時再送過去。
在flash remoting 中也同樣提供了這種功能,但以往只有使用Macromedia版的remoting adapter才能正確發揮功能,也就是說如果不是 coldfusion, jrun, remoting for .net之類的正牌產品,這部份功能要不就是不完整,要不就是完全爛掉。
Amfphp 是php版的flash remoting, open source並完全免費。過去amfphp在pageable recordset上的表現可說是非常糟糕,大部份人從來都無法真正實作成功;但隨者patrick加入amfphp開發團隊後,最近amfphp的表現可說是突飛猛進,快速逼進商業產品的水準。
目前最新版的amfphp是 pre-v1.0 milestone 2 (MS2),也就是v1.0正式發表前的最後一個beta,在這個版本裏終於開始有非常完整的pageable recordset功能。
有鑑於MS2 版中的pageable recordset實作手法有大改變,而目前網路上所有的教學文件都尚未更新,因此本文將以實際的例子介紹如何使用amfphp 的pageable recordset,並詳細解釋它的運作原理與 flash 端 RecordSet 配合的方式。
◆下載與安裝
請參考第一篇教學。
◆pageable recordset運作原理
在正式開始前我們先花點時間瞭解一下到底pageable recordset是怎麼個運作法。
首先,pageable recordset的用途在於,如果你在server端有100筆資料,通常不會全部傳回client端,而是以分頁的方式,例如每頁20筆資料共分五頁,然後當user按「下一頁」時才依序傳回需要的資料。
一般來說要做到pageable recordset有兩種方式:
1、 先在server端將100筆資料 query出來,放在session中備用,然後傳回需要的部份。
2、只先query出總資料量為100筆,然後用類似 mysql limit的語法一次撈20筆出來回傳。
第1種做法好處是可以減少與database連線的次數,並且資料存放於記憶體中理論上存取速度會非常快,但缺點則是session會吃掉大量資源,如果許多user同時連線並個自保有自已的session data,那 app server往往會撐不住而當掉。
第2種做法的好處則是不會消耗大量server資源,它在有需要時才去跟db撈出資料,但缺點也就是要頻繁的與db連線,此時良好的db connection management (pooling)就很重要。
以afmphp來說,它採取的是第2種方式,當 flash client一連線時,它會先query出資料的總筆數並回傳給flash, 之後就由flash內的RecordSet class來負責決定分頁方式與每次的取回資料量。
因此從這個描述中,大家可以感覺到整個pageable recordset的運作原理是需要下面兩者交互配合才能達成。
1、amfphp的分頁query功能
2、flash RecordSet 的分頁取回功能
有了基本認識後,接下來我們就開始實作吧。
◆flash 製作
首先我們製作好flash client 端的檔案,這個程式很簡單,只要拉一個 DataGrid與button元件到畫面上即可。

程式碼的部份如下:
Actionscript:
-
//remoting related
-
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;
-
import mx.events.*;
-
//start debugging so we can see debug info in NCD.
-
NetDebug.initialize();
-
//setting gateway
-
var gateway:String = "http://localhost/pageableRecordSet/gateway.php";
-
respGeneral = new RelayResponder(this, "contactReceived", "contactFailure");
-
_service = new Service(gateway, null, "PRecordSet", null, respGeneral);
-
//
-
var pc:PendingCall = _service.getFullList(["Name", "Region", "Code"]);
-
//
-
dg.columnNames = ["Code", "Name", "Continent"];
-
//
-
function contactReceived(re:ResultEvent):Void{
-
var tmp:RecordSet = RecordSet(re.result);
-
tmp.setDeliveryMode("page", 10, 2);
-
dg.dataProvider = tmp;
-
};
-
//
-
btnRefresh.clickHandler = function(){
-
dg.removeAll();
-
var pc:PendingCall = _service.getFullList(["Name", "Region", "Code"]);
-
}
◆php端製作
這個例子中我們是使用 windows + apache 2 + php 5.04 + mysql 4.1 + amfphp ms2,但基本上在其它平台或程式版本也應該沒問題(注意amfphp至少要是ms1以上才行)
首先我們在apache的web folder (/htdoc)下建一個專案資料夾:
C:\Program Files\Apache Group\Apache2\htdocs\pageableRecordSet
然後在pageableRecordSet下建一個 service 資料夾
C:\Program Files\Apache Group\Apache2\htdocs\pageableRecordSet\services
在這個新建的資料夾內,建立一個新的php程式,名稱為 PrecordSet.php
它的程式碼如下:
PHP:
-
<?
-
class PRecordSet
-
{
-
var $dbhost = "localhost";
-
var $dbname = "test";
-
var $dbuser = "root";
-
var $dbpass = "";
-
-
function PRecordSet()
-
{
-
$this->
conn =
mysql_pconnect($this->
dbhost,
$this->
dbuser,
$this->
dbpass);
-
-
-
$this->tablename = "country";
-
-
$this->
methodTable =
array(
-
"getColumnNames" =>
array(
-
"description" => "Return column names from table",
-
"access" => "remote",
-
-
),
-
-
"description" => "Return a full list of table records, pass as argument an array of columns to be returned",
-
"access" => "remote",
-
"arguments" =>
array("arrayOfColumns"),
-
"pagesize" => "10",
-
),
-
);
-
-
}
-
-
-
function getColumnNames()
-
{
-
-
return $query;
-
-
}
-
/*
-
前面有幾個參數都沒關係,但
-
最後兩個參數最重要:$offset, $limit 會被amfphp自動呼叫
-
因此,整個sql語法也要用sprintf來寫。
-
*/
-
function getFullList($ar_col, $cursor, $limit)
-
{
-
//count it first
-
$this->countQuery = "SELECT COUNT(*) AS recordCount FROM country";
-
//
-
return mysql_query(sprintf("select * FROM %s ORDER BY Name ASC Limit %d, %d",
$this->
tablename,
$cursor,
$limit));
-
}
-
/*
-
所有需要 分頁 的function, 都要加上這個 _count,讓amfphp自動去呼叫
-
-
*/
-
function getFullList_count(){
-
-
-
return $row['recordCount'];
-
}
-
}
-
?>
上面的程式碼中,比較重要的幾點如下:
-amfphp端都是以class的型式存在,因此等於是在寫一個 php class。但一開頭的method table 非常重要,裏面有許多關鍵字可設定這個class的運作行為。
-第26行的pagesize => 10 是告訴amfphp 我希望每頁只傳回10筆資料;這是最關鍵的一行設定,但還需其它地方配合。
-第44行開始的getFullList($ar_col, $cursor, $limit)就是要曝露給client端呼叫的remote method, 名稱為 getFullList,裏面有三個參數。前面的$ar_col 是我們要取回的欄位名稱,實際上這裏要放多少個參數都沒關係,視實際需要而定;比較重要的是最後兩個$cursor與 $limit 參數,這兩個參數是amfphp日後進行分頁取回時會自動填入資料的地方,也就是下面query中limit的兩個關鍵字。
其中$cursor 是指目前所在位置,例如第10筆資料,而$limit則是將下來要取回的資料量,例如假設你設定一次要取回2頁,每頁10筆資料,那麼 $limit就會是 20,而整個function call就會是 getFullList(“some columns”, 10, 20),我們在下面的應用中會再解釋一下這部份。
這裏你只要記住:不管前面有幾個參數(例如$ar_col, 最後兩個一定要是 $cursor, $limit)
-第47行也是必備的項目,從query字串中就可以看出它的功能是在 count()全部的資料量,好在第一次連線時回傳給flash端做為日後分頁計算的基礎。
-第49行的query則是最重要的地方,請注意最兩點。
首先是sprintf的使用,這是一個很傳統的function,主要功能是將 %s, %d這樣的變數動態替換成後面的參數。
第二點則是 limit 的使用,在mysql中limit最常被用來進行分頁處理,它的第一個參數是啟始點(例如要從第10筆資料開始),第二個參數是資料量,例如(20筆),因此透過limit我們就可以從第10筆開始取回20筆資料。
-第55行的getFullList_count()則是amfphp新增的實作手法,這個function基本上就是將前面的getFullList加上 _count,而它主要的功能是用來計算query結果的資料量,這點從56-58行的程式碼中就可看出。它利用前面 COUNT(*) AS recordCount 將計算結果存在 recordCount這個欄位中,然後用$row = mysql_fetch_assoc($q) 與 $row['recordCount'] 來取得計算後的總量。
這支程式是amfphp 內部運作時會自動呼叫的,因此一定要有,但它的名稱不一定要是 functionName_count()這樣,可以在method table內增加一個 countMethod => “my_count”來指定要使用的名稱。
◆實際執行
在實際執行前你需要先放點東西到mysql裏才行,請下載本教學的範例檔案,裏面有個 db.sql 檔,它會在mysql內建的test database內新增一個 country table,這就是我們要用的測試資料。
接者請確定你的web server, php, mysql都正常運作,並且也正確安裝了 amfphp ms2,然後 project folder 名稱正確,service folder裏也有剛寫好的 PrecordSet.php。
最後記得打開 NetConnection Debugger 簡稱NCD (Window > Other Panel > NetConnection Debugger)以方便觀察flash與php間的資料傳輸情況。
當一切就續後就可以執行flash 的 ctrl-enter,此時在NCD中會看到下面的畫面:

這張畫面中顯示當flash第一次與amfphp連線執行 getFullList()後,amfphp傳回了一堆資料,其中最重要的就是:
mTotalCount: 57 這行告訴flash你要求的資料總共有57筆。
mRecordsAvailable: 0 目前我還沒傳回任可一筆資料。
當這些資訊回傳給flash 後,接下來就是flash RecordSet的責任去決定該如何取回這57筆資料,請注意我們在flash裏面寫的程式:
Actionscript:
-
function contactReceived(re:ResultEvent):Void{
-
var tmp:RecordSet = RecordSet(re.result);
-
tmp.setDeliveryMode("page", 10, 2);
-
dg.dataProvider = tmp;
-
};
這個contactReceived就是當初設定的 remoting callback, 當amfphp傳回資料時,就是由它去負責接收並做後續處理。在這個function裏我們設定了 setDeliveryMode("page", 10, 2), 這是 RecordSet內建的一個指令,透過這句話我們決定接下來的取回方式是”page”,每次10筆資料,並且預先取回2頁。
然後我們使用 dg.dataProvider = tmp,也就是將recordset餵給 datagrid的dataProivder,就可以順利顯示出來。
而這樣設定後最神奇的地方在於,當user捲動到下一頁時,recordset會知道資料還在server,因此自動跑去跟amfphp要求下面兩頁的資料,請看下圖。

請注意圖中,flash自動去呼叫amfphp中的PageAbleResult.getRecords()這支指令,並且傳回三個參數,第一個參數是session id,這個不重要先不管它,第二個參數則是目前 cursor 所在位置,第3個參數則是flash希望先取回30筆資料備用。
但為什麼是30筆呢?當初我們明明設定是先取回2頁啊!原因是”page”模式下,ReocrdSet永遠會自動取回目前所需的頁面,並且pre-fetch 使用者指定的頁面,因此目前cursor在1,它必需先取回自已所在的第1頁,然後預抓回2頁,也就是總共3頁共30筆資料,這就是 1, 30的由來。
之後RecordSet就會視user的捲動情況而決定何時該向amfphp要求更多的頁面,你可以試試捲動datagrid,此時會發現NCD裏出現一狗票的連線與取回記錄,如下圖

注意裏面有新增了幾個 call指令,這就是RecordSet 在進行自動取回,另外也特別注意倒數第二行的release(),當server 端的所有資料都取回後,ReocrdSet 會透過這指令告訴amfphp可以丟棄存放於server端的分頁記錄順便清空記憶體,等於是某種形式的garbage collection。
透過以上的例子,大家應該可以瞭解amfphp的pageable recodset運作原理,理論上來說只要支援dataProvider與 RecordSet 的元件都會自動支援這個分頁功能,例如combobox, listbox, datagrid 等,但tree就不行,因為它只吃xml data,除非你能替RecordSet 加上即時rs2xml的功能。
◆資料取回模式釋疑
RecordSet在取回資料時共有三種模式,分別解釋如下:
-onDemand: 這是預設的模式,也就是一次取回一筆資料,只有當需要時才連線向amfphp提出請求。好處是每次取回的資料量少,反應速度快,缺點則是會頻繁的app server連線,如果網路速度不快反而會因為lag造成使用上的不變。
-page: 以「頁」為單位取回資料,這是最常見的應用方式,它還可搭配另外兩個參數,分別是pagesize(每頁的資料筆數)與numPrefetchPages(預先取回的頁數),以我們的例子來說,setDeliveryMode(“page”, 10, 2)就是設定取回模式為page, 一頁10筆資料,預先取回2頁。
-fetachAll:這個模式會將所有資料一次取回,但可透過pagesize這個參數來預做分頁,預設值是每頁25筆資料。
一般如果會用到分頁功能,通常不二的選擇就是”page” mode,並且視需要決定每頁的筆數與預先取回量。
◆pageable recordset使用注意事項
amfphp的 pageable recordset 設計與使用上不像coldfusion 那樣方便,但那是因為許多背景因素造成,以open source project來講,能有這樣的表現已經是非常令人讚賞,只要你知道日常操作中該避開的陷井就一切ok。
-amfphp無法處理極大量的page,據各討論list上得到的結論,五千筆是一個上限。
-amfphp使用limit 語法,這是mysql獨有的指令,在mssql上可用select top n 的方式達成,但這牽涉到改寫amfphp的程式。
-php端的 functionName()中要記得加上 $cursor, $limit 兩個參數,這是供amfphp內部分頁使用,少了它們分頁就玩完了。
-php端一定要有 functionName_count()這個指令,也就是每個需要分頁的method都要伴隨者一支count method,才能計算正確的資料量回傳給recordset。
-php端的 method table要有 pagesize => “10”這樣的分頁設定,這是amfphp在第一次回傳資料時要參考的數字,如果這裏沒設定,amfphp就會認定你沒有分頁的需求而將全部資料一次都丟回client端了(這也是目前amfphp example 所犯的錯誤,可能是作者忙者改程式碼還沒空修正這個範例)
◆檔案下載
這個教學的範例檔案可按此下戴。程式碼中已加上大量註解,因此應該很容易理解。
如有任何疑問歡迎隨時提出。
| by admin