FLEX on PHP , ZendAMF 的魔力 ValueObject 對應
在學習各種的 FRAME WORK 一定常常聽到 MVC 這個名詞,他的意思是將 資料,控制,檢視 三個不同的行為分開處理,如果要做到這樣, Value Object 就是一個很重要的東西了,在資料層面來說你應該把資料放入 Value Object ( 之後簡稱為 VO ) 中,然後再交給各種控制元件或是檢視元件來做處理,ZendAMF 可以很快速的幫我們完成這件事情。
圖片 : 看起來很簡單,但是卻是開發大專案很重要的喔,也是 ZENDAMF 提供的好功能
NOTE :
實作本篇文章之前,請先閱讀本站 ZENDAMF 其他相關文章,因為設定會照著之前的設定來實作,謝謝,高手可以忽略,謝謝。
Value Object 可能很多人很陌生,其實並不用太害怕,JAVA 用多的人應該對他也很熟悉,簡單的說,他就是一個預先寫好的 OBJECT,並且設定好屬性,這個定義好的屬性,未來就可以讓許多不同的元件使用,並且資料內容是一致的。
舉個例來說吧,index.mxml 是我們的主程式,在主程式中我們包含了很多不同的應用系統,A系統,B系統,C系統,當使用者登入後,在取得使用者的資料後 ( 除了帳號之外還有其他大約 10 個項目的資料 ),這時候你該如何在 A B C 三個系統都可以取得使用者的資料呢 ? 是每個系統都利用使用者的 ID 去資料庫在取得一次內容嗎 ? 還是將 10 個字串一個一個傳入 A B C 三個系統 ? 還是會透過取得上層物件的方式 ? 又或許你可以 NEW 一個 OBJECT 來存放使用者資料,但是這樣 A B C 三個系統會知道 OBJECT 內有甚麼屬性可用嗎 ? 是的 , 類似 NEW 一個 OBJECT ,只是我們先將他取個名字,並且幫他定義好屬性,這樣子我們在取用的時候,是不是就知道裡面有甚麼東西了呢。
簡單的 VO 寫法 vo.as
1 2 3 4 5 6 7 8 9 10 | package { public class vo { public var user_id:String; public var user_name:String; public var user_age:int; //諸如此類屬性 } } |
這個時候我們在取用的時候就會出現屬性可以使用。
圖片 : 終於我們不用再猜人家給我們的 OBJECT 裡面到底放了甚麼
那這個東西又跟 ZENDAMF 扯上什麼關係了,老實說,今天我為了這個問題卡了一天,但是事實上我是打錯字了,卻被卡了一天,真的是覺得自己能力太差了,好了,離題了,以前,我們不用 ZENDAMF ,我們使用 AMFPHP 來寫這種從資料庫取回資料的程式,FLEX 向 AMFPHP 要求使用者資料,AMFPHP 回傳 Result 給 FLEX ,這時候回傳的會是一個 OBJECT,我們必須一個一個的將回傳的資料塞入 VO 中,就像這樣。
1 2 3 4 5 6 7 8 9 10 11 12 | <mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
public function resultHandler(event:ResultEvent):void{
var myVO:vo = new vo();
myVO.user_id = event.result.user_id;
myVO.user_name = event.result.user_name;
myVO.user_age = event.result.user_age;
}
]]>
</mx:Script> |
還好我們只有三個屬性,如果有 30 個你不就要哭了,難道用 VO 就應該這麼累嗎 ? 其實使用 ZENDAMF 你有更快速的綁定 ActionScript 與 PHP 之間的 VO。我看了原廠的說明,他提供了三個方式來綁定 VO ,真的是有看沒有懂,不過還好最後找到了作者的一段影片,才恍然大悟我有一個地方打錯字。
ZENDAMF 提供了三種方式綁定
- 第一種,你可以在 GATEWAY 上設定你的 CLASSMAP
1 2
// Map the ActionScript class 'ContactVO' to the PHP class 'Contact': $server->setClassMap('ContactVO', 'Contact');
- 第二種,你可以在 PHP VO 上加上參數
public $_explicitType = 'ContactVO';
1 2 3 4
class Contact { public $_explicitType = 'ContactVO'; }
- 第三種,你可以在 PHP VO 上增加一個動態的方法
1 2 3 4 5 6 7
class Contact { public function getASClassName() { return 'ContactVO'; } }
就是這三種方法,不過真的有看沒有懂,我們來做個示範練習吧。
我們建立一支程式,他會向後端 PHP 取得客戶的聯絡資料,並且放入 VO 中供其他的元件取用,首先我們先來建立 ActionScript 的 VO
ContactVO.as
1 2 3 4 5 6 7 8 9 10 11 12 13 | package { [Bindable] [RemoteClass(alias="ContactVO")] public class ContactVO { public var id:int; public var firstname:String; public var lastname:String; public var email:String; public var mobile:String; } } |
接下來我們建立好 MXML 的主程式,我們建立兩個按鈕,一個按鈕取得客戶資料並且放入 VO 中,另一個按鈕我們將 VO 的資料送回 ZENDAMF 處理過後再回傳。
UseVOtest.mxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" fontSize="14">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
[Bindable]
private var contactVo:ContactVO = new ContactVO();
private function getCustomerData():void{
this.ro1.getCumstomer();
}
private function reSetCustomerData():void{
this.ro1.setCustomer(this.contactVo);
}
private function resultHandler(event:ResultEvent):void{
this.contactVo = event.result as ContactVO;
}
]]>
</mx:Script>
<mx:RemoteObject id="ro1" endpoint="allgateway.php" destination="zend" source="Customer" result="resultHandler(event)"/>
<mx:Form width="600">
<mx:FormItem label="編號">
<mx:Label text="{this.contactVo.id}"/>
</mx:FormItem>
<mx:FormItem label="姓">
<mx:TextInput text="{this.contactVo.firstname}"/>
</mx:FormItem>
<mx:FormItem label="名">
<mx:TextInput text="{this.contactVo.lastname}"/>
</mx:FormItem>
<mx:FormItem label="電子郵件">
<mx:TextInput text="{this.contactVo.email}"/>
</mx:FormItem>
<mx:FormItem label="行動電話">
<mx:TextInput text="{this.contactVo.mobile}"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button label="取得原始資料" click="getCustomerData()"/>
<mx:Button label="取得修改後資料" click="reSetCustomerData()"/>
</mx:FormItem>
</mx:Form>
</mx:Application> |
接下來我們來建立對應到 PHP 的 VO CLASS ,並且我們加上參數對應到 AS 的 VO CLASS 名字。
services\ContactVO.php
1 2 3 4 5 6 7 8 9 10 11 | <?php class ContactVO{ public $id = 0; public $firstname =""; public $lastname =""; public $email =""; public $mobile =""; } ?> |
最後我們來建立主要的 CUSTOMER 取得客戶資料的 PHP CLASS 吧,因為是範例,我們就不真正從資料庫取出資料了,我們新增一個 PHP VO 然後我們給他一些假的資料,並且回傳給 FLEX , 至於重設客戶資料的方法,我們也不寫入資料庫囉,我們把取得的 VO 修改一下內容,再重新丟回給 FLEX 就可以了。
services\Customer.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?php require_once 'ContactVO.php'; class Customer { function getCumstomer(){ $contact = new ContactVO(); $contact->id = 1; $contact->firstname = "Ausir"; $contact->lastname = "Lo"; $contact->email = "程式逗設計@corausir.org"; $contact->mobile = "8825252"; return $contact; } function setCustomer($contact){ $contact->id = 999; $contact->firstname = $contact->firstname." 修改完成"; $contact->lastname = $contact->lastname." 修改完成"; $contact->email = $contact->email." 修改完成"; $contact->mobile = $contact->mobile." 修改完成"; return $contact; } } ?> |
最後我們再來修改一下 GATEWAY 吧,因為我們使用官方建議的第一種方法,在 GATEWAY 加上 CLASSMAP ,這裡又有一個陷阱,又是我卡關的地方了,本來因為我們使用了 addDirectory 這個方法將資料夾內所有的 CLASS 都引用,但是在雙向的 VO 溝通上如果我們沒有在特別設定 SETCLASS 會造成 VO 只可以單向溝通,也就是說 VO 只可以從 PHP 新增好後丟到 FLEX ,如果 FLEX 新增好 AS 的 VO ,丟到 ZENDAMF ,這時候一定會跳錯誤死給你看,所以記得一定要兩行都加喔。我就是一開始做的時候沒有 SETCLASS 一直跳錯誤不知道為什麼。來修改之前的 allgateway.php 檔案吧。
allgateway.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?php //定義 library 位置 define ('P_S', PATH_SEPARATOR); set_include_path('.' .P_S .'library' .P_S .'../application/models/' .P_S .get_include_path()); //引入 AMF SERVER 類別 require_once 'library/Zend/Amf/Server.php'; require_once 'services/Customer.php'; $server = new Zend_Amf_Server(); //將整個資料夾都納入 SERVER 內 $server->addDirectory(dirname(__FILE__).'/services/'); //注意,雙向 VO 溝通一定得設定 setClass 喔 不要忘記了 $server->setClass(Customer); //前面的字串代表 AS 的 VO 別名 , 後面的代表 PHP 的 VO CLASS $server->setClassMap("ContactVO","ContactVO"); $result = $server->handle(); echo $result; ?> |
都準備好了,這時候執行應該可以取得資料,並且也可以順利修改客戶資料了,實作範例。
Value Object 的用途很廣喔,請大家務必要學會啦,ZENDAMF 也差不多到這裡告一段落了,因為連官方那邊也沒有在更多的文章了,其他的用法應該都是 PHP 的用法了,謝謝各位看官的觀賞,我們下次見。
Random Posts
Loading…
相關文章 :












補充說明 :
我在把原廠提供的兩種對應方式寫法補上
第二種
第三種
三種方法選一種來寫就可以囉
備註 : 如果選的是第二或第三種方法 setClass 那邊還是不要忘記寫喔 !! 會造成單向 VO 傳輸
延伸閱讀 :
Flex and PHP: remoting with Zend AMF
Zend_Amf-classmapping 影片實作範例
實用技巧 :
如果你是 VO 的老手,或是新手要進階了,每次都要新增一堆變數
如果寫的正式一點還不可以把屬性寫成 PUBLIC
要寫 PRIVATE 並且透過 SET 與 GET 來取用
哇喔~ 這樣 10 個屬性就要 20 個方法 有沒有這麼累阿~~
請看這位美女達人~ 他用 AIR 幫你寫了一個自動產生 AS 的 VO 程式喔~
非常的好用呢~ 省力不少~
請到這邊來
[AIR] Value Object classes creator 提供者 Erin Lin
不知道他改天會不會開發 PHP 版 XD 偷笑中~@@ 難道要我自己開發嗎? 哈~
您好!
請問一個 vo 問題,新手一直搞不懂:
我在這個範例(A系統)裡多加了一個 MODEL(B系統),
在 B 系統裡,我怎麼去取出 vo 的值呢?
我得到的都是空值,不同系統不能直接存取嗎?
model1.mxml
在主程式我只多了個
程式碼貼不上去 =.=
@小老虎
@小老虎
你要先將 A 系統建立起來的 VO 傳進去 B 系統
才可以取得 A 系統所建立的 VO
類似這樣
程式碼請用
CODE 標籤 或是 PRE 標籤 包起來~~
您好!
請問一個 vo 問題,新手一直搞不懂:
我在這個範例(A系統)裡多加了一個 MODEL(B系統),
在 B 系統裡,我怎麼去取出 vo 的值呢?
我得到的都是空值,不同系統不能直接存取嗎?
model1.mxml
在主程式我只多了個
其他都是沿用您的程式碼。
我看不懂這是什麼意思?我的系統 B 就是那個 model1.mxml
var systemB:SystemB = new SystemB();沒關係~
用 < 中括號 來寫 PRE 標籤
在包你的程式碼是是看
等等我再來刪掉
這樣寫
您好!
請問一個 vo 問題,新手一直搞不懂:
我在這個範例(A系統)裡多加了一個 MODEL(B系統),
在 B 系統裡,我怎麼去取出 vo 的值呢?
我得到的都是空值,不同系統不能直接存取嗎?
model1.mxml
在主程式我只多了個
其他都是沿用您的程式碼。
我看不懂這是什麼意思?我的系統 B 就是那個 model1.mxml
var systemB:SystemB = new SystemB();
SystemB 是從哪裡來的?
怎麼你的程式碼還是消失了呢~?@@
詭異阿~~
這樣子你上傳到哪邊去我來下載吧 XD
回覆不能使用標籤的樣子,都會無效化。
我把<>用全型的看看。
好!
請問一個 vo 問題,新手一直搞不懂:
我在這個範例(A系統)裡多加了一個 MODEL(B系統),
在 B 系統裡,我怎麼去取出 vo 的值呢?
我得到的都是空值,不同系統不能直接存取嗎?
model1.mxml
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Module xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”vertical” width=”100%” height=”100%”>
<mx:Script>
<![CDATA[
import vo.ContactVO;
[Bindable]
private var contactVo:ContactVO = new ContactVO();
]]>
</mx:Script>
<mx:Form width=”600″>
<mx:FormItem label=”編號”>
<mx:Label text=”{this.contactVo.id}”/>
</mx:FormItem>
<mx:FormItem label=”姓”>
<mx:TextInput text=”{this.contactVo.firstname}”/>
</mx:FormItem>
<mx:FormItem label=”名”>
<mx:TextInput text=”{this.contactVo.lastname}”/>
</mx:FormItem>
<mx:FormItem label=”電子郵件”>
<mx:TextInput text=”{this.contactVo.email}”/>
</mx:FormItem>
<mx:FormItem label=”行動電話”>
<mx:TextInput text=”{this.contactVo.mobile}”/>
</mx:FormItem>
</mx:Form>
</mx:Module>
在主程式我只多了個
其他都是沿用您的程式碼。
我看不懂這是什麼意思?我的系統 B 就是那個 model1.mxml
var systemB:SystemB = new SystemB();
SystemB 是從哪裡來的,怎麼去定義?
主程式只加了個
<mx:ModuleLoader id=”mod1″ url=”model1.swf”/>
我誤會你的意思~
我以為你的 FLEX 有寫元件~
你這樣寫沒有錯阿~ 是這樣取得沒有錯
但是因為你這樣只有取出
你的 VO 還沒有設定資料給他~ 所以取出來當然就是空值嚕
你應該這樣
mx:Module 我還沒有用過
XD 我都用元件在寫
不過應該相差不多才是~
我的意思是:
在您的範例裡已經有給 vo 值了,我就當他是[主程式 A],
我要在[B 程式](model)直接拿來用就好了,不需再跑一次到伺服器裡取資料,
可是使用 MODEL ,好像不能直接取主程式 A 裡的值。
因為我想寫一個進銷存來用,用元件寫的話,檔案不是會變很大嗎?
所以才想用 model 來做,這樣可以分開成很多小程式,需要的時候在載入就好了。
OK 了解你意思了
先不論是 component 還是 module
先設定 A.mxml 是 application 主程式
B.mxml 是 component 因為 module 我不能確定
B的寫法 你要寫一個方法來接收已經有資料的 VO
private function setVO(vo:ContactVO){ this.vo = vo ; // 傳入資料 }而A的寫法應該在 NEW 出元件的時候丟入 VO
這樣子 B 元件才拿的到 A 主程式的資料
不知道這樣說是不是正確
或是你要在建構的時候就丟入 VO
謝謝!我先試看看元件的方式吧!
new B,這個 B 是元件 id 嗎?
不是
我的意思是 B.mxml
new 出來的就會是 new B();
請教一個問題…卡這關卡很久了
若是ZendAMF要搭上CodeignIter的做法?爬文爬了很久,只找到兩篇,但都是AMFPHP配CodeignIter…
AMF_Codeigniter_Library_No_Zend_No_Hooks_Etc
AMF_Flash_Remoting_with_Zend_and_CI
@羊
你好喔~
因為我本身也沒有用過 CodeignIter 這個 FW
不過我想如果你單純把 ZENDAMF 拿來用的話
應該是差不多吧~~ XD
我也是一知半解中
或許可以討論看看 CC
@Ausir
謝謝你!
我再研究看看,有研究出來一定分享出來,謝謝!
@羊
加油 ^_^”
我今天也要開始來去再進修 FLEX 嚕…. >”<
地獄訓練
@Ausir
嗨,我研究出來了,成功地將ZENDAMF跟CodeIgniter整合起來了,不過礙於目前工作忙錄,可能要過一段時間才能分享出來,抱歉喔!
@羊
你沒有把你的網址交出來 ^_^
大家可以互相看看 CCC
很想看你說的那套 FW 多長進長進
我就是不長進阿 >”<…
@Ausir
哎…… /_\
今天在做這project時又發現問題,用codeIgniter嵌一隻swf是ok的,但這隻swf要再load外部的swf就一片空白…這是怎麼個回事呢??? /_\
@羊
SWF 嵌入 SWF 應該是不會有問題
可能是因為你另一個 SWF 你有用到 STAGE 屬性
所以就錯誤了~?
@Ausir
沒耶,我只是做簡單的測試,要利用ExternalInterface抓網址而已,而且用別的swf試過,swf從flash按ctrl + enter publish出來是讀得到,開瀏覽器 http://localhost/…. 就掛掉了 /_\ 不曉得是不是codeIgniter的問題
沒用過的 FW 所以我也不是很清楚了 >”<
@Ausir
我…我再研究看看……..
@羊
去PTT問了php高手終於解決了這個問題,問題出在絕對路徑與相對路徑,通常我們寫flash讀別隻swf通常都是寫相對路徑,但在codeIgniter裡是沒有相對路徑這回事,所以要用絕對路徑,把嵌swf的php裡的swf路徑改成絕對路徑,還有flash裡也改成絕對路徑就ok了!!
@羊
原來是這樣子
不過一般來說 MVC 的 FW 都會把路徑轉向
所以都要稍微注意一下 SOURCE 的位址
我還是不懂$server->addDirectory(dirname(__FILE__))有什麽用。。。
請問,這個函數到底有什麽用呢?
@小江
這個函數的意思是說
要把 services 這個資料夾內的所有 PHP CLASS 通通載入
不用一隻一隻 PHP 分別載入
你好,大大有提到更進階的技巧的VO,將VO的設為private,然後再用set和get,但是,配合上zendAmf,如果AS和PHP兩個都不設定成public好像就沒辦法互傳屬性值說..還是大大有其他的方法,可以使用這更進階的技巧~^^?
你好:
不久前像你這樣 php 回傳 class, flex 再用 class 去接,我用 amfphp 就能正確處理了~ 所有的 member variable 都是 public 的。
@SanC
SET 跟 GET 是標準的物件導向觀念 ^^
如果有機會我會再利用解釋看看
@Jimmy
嗯嗯~~
PUBLIC 比較麻煩是如果傳入的數值需要更改過再套用
就比較麻煩
變成資料無法有足夠全線管控