2009/07/22 カテゴリ : Tech  ActionScript  symfony  Flex  sfAmfPlugin 

続・Flex4とsymfonyを連携させて遊んでみた。

屋内の寒さと、屋外の暑さの差で完全に夏バテ気味の橋本です、こんにちは。

早く秋がきてほしいですね。
秋いいよ、秋…。

はい。というわけで、みなさんも体調管理には気をつけてくださいませ。

さて、今回は前回に引き続き、Flex4 × Symfonyのお話です。

前回はsfAmfPluginの使い方と、データの保存処理について書きました。今回は引き続きデータの取得について書いていこうと思います。

(ちなみに、sfAmfPluginの2009/07/22現在の最新版はver.1.4.1です。前回使っていたver.1.3.0のバグがいくつか修正されているようなので、皆様こちらを使用しましょう。)

データの取得についても、前回と同様に、まずsymfony側でサービスのメソッドの作成をします。

とりあえず、前回の記事で作成した保存用のメソッドに加え、取得用のメソッドを作成します。

サービス
  1. <?php
  2.  
  3. // lib/services/frontend/user/RegisterService.class.php
  4.  
  5. class RegisterService extends sfAmfService {
  6.   // ユーザデータを保存する
  7.   public function saveUserData($user_data) {
  8.     $user = new User();
  9.     $user->fromArray($user_data);
  10.     $user->save();
  11.  
  12.     return 'OK';
  13.   }
  14.  
  15.   // ユーザデータを取得する
  16.   /**
  17.      * @AmfReturnType("ArrayCollection")
  18.      */
  19.   public function getUserData() {
  20.     $user_list = Doctrine::getTable('User')->getUserData();
  21.     return $user_list;
  22.   }
  23. }

モデル
  1. <?php
  2.  
  3. // lib/model/doctrine/UserTable.class.php
  4.  
  5. class UserTable extends Doctrine_Table
  6. {
  7.   public function getUserData() {
  8.     $ret = array();
  9.  
  10.     $rec = $this->createQuery('u')
  11.       ->execute();
  12.  
  13.     foreach ($rec as $user) {
  14.       $ret[] = array($user->id, $user->name, $user->email, $user->phone);
  15.     }
  16.     return $ret;
  17.   }
  18. }

RegisterService.class.phpの保存用メソッド、getUserData()のコメント。
このコメントはアノテーションになっており、Flex側で受け取った際の戻り値の型を指定することができます。
今回は、戻り値をDataGridの中で使用するため、AllayCollection型で返します。

次にFlex側です。
ソースはこんな感じ。(またまた適当ですみません。)

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  3.              xmlns:s="library://ns.adobe.com/flex/spark"
  4.              xmlns:mx="library://ns.adobe.com/flex/halo"
  5.              minWidth="1024"
  6.              minHeight="768"
  7.              creationComplete="loadUserData()">
  8. <fx:Script>
  9. <![CDATA[
  10.   import mx.rpc.AsyncResponder;
  11.   import mx.rpc.AsyncToken;
  12.   import mx.collections.ArrayCollection;
  13.   import mx.automation.IAutomationObject;
  14.   import mx.controls.Alert;
  15.   import mx.rpc.remoting.RemoteObject;
  16.   import mx.rpc.events.FaultEvent;
  17.   import mx.rpc.events.ResultEvent;
  18.      
  19.      [Bindable]
  20.   private var userDataList:ArrayCollection;
  21.   
  22.      private function loadUserData():void {
  23.        // サービスの呼び出し
  24.        var token:AsyncToken = remote.getUserData();
  25.        // ResultEventFaultEventの処理を登録
  26.         token.addResponder(new AsyncResponder(successLoadFunc, faultLoadFunc));
  27.      }
  28.      
  29.      private function saveUserData():void {
  30.        // フォームで取得したデータを入れる配列
  31.        var data:Array = new Array();
  32.        
  33.        data['name'] = nameForm.text;
  34.        data['email'] = emailForm.text;
  35.        data['phone'] = phoneForm.text;
  36.        
  37.        // サービスの呼び出し
  38.        var token:AsyncToken = remote.saveUserData(data);
  39.        // ResultEventFaultEventの処理を登録
  40.        token.addResponder(new AsyncResponder(successSaveFunc, faultSaveFunc));
  41.      }
  42.      
  43.      private function successLoadFunc(e:ResultEvent,obj:Object = null):void {
  44.     // 明示的にキャストしないとエラーが出て、FlashBuilderさんがコンパイルしてくれません…
  45.     userDataList = ArrayCollection(e.result);
  46.   }
  47.   
  48.   private function faultLoadFunc(e:FaultEvent,obj:Object=null):void{
  49.     Alert.show(e.toString(), "Error");
  50.   }
  51.   
  52.   private function successSaveFunc(e:ResultEvent,obj:Object = null):void {
  53.     Alert.show(e.result.toString(), "Registerd");
  54.     // フォームをリセットして、データを再読み込みします。
  55.     resetUserData();
  56.     loadUserData();
  57.   }
  58.   
  59.   private function faultSaveFunc(e:FaultEvent,obj:Object=null):void{
  60.     Alert.show(e.toString(), "Error");
  61.   }
  62.   
  63.   private function resetUserData():void {
  64.     nameForm.text = "";
  65.     emailForm.text = "";
  66.     phoneForm.text = "";
  67.   }
  68.  
  69. ]]>
  70. </fx:Script>
  71.  
  72. <fx:Declarations>
  73. <mx:RemoteObject 
  74.   id="remote"
  75.   endpoint="http://amf_sample/amfgateway/amf"
  76.   source="frontend.user.RegisterService"
  77.   destination="hoge" 
  78.   showBusyCursor="true"
  79. />  
  80. </fx:Declarations>
  81.   <mx:TabNavigator x="80" y="35" width="485" height="430">
  82.     <mx:Canvas label="save" width="100%" height="100%">
  83.       <s:Button x="80" y="270" label="Save" id="btnSaveUserData" click="saveUserData()"/>
  84.       <s:Button x="200" y="270" label="reset" id="btnResetUserData" click="resetUserData()"/>
  85.       <mx:Label x="50" y="40" text="Name"/>
  86.       <mx:Label x="50" y="120" text="Email"/>
  87.       <mx:Label x="50" y="200" text="Phone"/>
  88.       <s:TextInput x="150" y="35" id="nameForm" width="240"/>
  89.       <s:TextInput x="150" y="120" id="emailForm" width="240"/>
  90.       <s:TextInput x="150" y="200" id="phoneForm" width="240"/>
  91.     </mx:Canvas>
  92.     <mx:Canvas label="Load" width="100%" height="100%">
  93.       <mx:DataGrid x="20" y="20" height="340" width="450" dataProvider="{userDataList}">
  94.         <mx:columns>
  95.           <mx:DataGridColumn headerText="ID" dataField="0"/>
  96.           <mx:DataGridColumn headerText="Name" dataField="1"/>
  97.           <mx:DataGridColumn headerText="Email" dataField="2"/>
  98.           <mx:DataGridColumn headerText="Phone" dataField="3"/>
  99.         </mx:columns>
  100.       </mx:DataGrid>
  101.     </mx:Canvas>
  102.   </mx:TabNavigator>
  103. </s:Application>

タブナビゲータを使って、入力画面と表示画面を分けてあります。

Flex側のポイントはAsyncTokenクラスです。
RemoteObjectを使ってサーバのサービスを呼び出すと、ResultEventやFaultEventにレスポンスが返ってきます。そのレスポンスを受けるのがAsyncTokenクラスになります。(なんだか説明がわかりにくくてすみません。)
また、AsyncTokenのインスタンスには、addResponderメソッドを使ってレスポンダを登録することができます。レスポンダ(AsyncResponderクラス)には、レスポンスがresultの場合の処理と、faultの場合のメソッドをそれぞれ登録することができます。

サービスからの戻り値は、ResultEvent、FaultEventのresultというプロパティに格納されています。

その他は簡単です。サービスから取得したデータをDataGridのdataProviderに指定した変数(今回はArrayCollection型。Array型でも大丈夫です。)に入れてるだけ。

では、早速動かしてみます。

まずは、前回作った登録側から。

最初はデータがありません。



データを登録します。



保存成功。



データを確認。更新されています。やったね。




というわけで、二回にわたって書いてきたFlex4 x Symfony。よく分からないエラーに悩まされた日々もありましたが、結果的にデータの登録と取得が問題なく出来るようになりました。ここまで出来れば、あとは応用でいろいろと面白いことができそうです。

意外と簡単ですので、皆さんも是非やってみてください。


※ちなみに、前回の作成例とコードが違うのは、間違って前回のデータを消してしまったためです。泣きました。皆さんも気をつけてください…。

コメントフォーム

認証
captcha_key
 
 

トラックバックURI

アシアルPHP書籍情報