その他

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

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

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

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

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

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

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

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

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

サービス


<?php
// lib/services/frontend/user/RegisterService.class.php
class RegisterService extends sfAmfService {
  // ユーザデータを保存する
  public function saveUserData($user_data) {
    $user = new User();
    $user->fromArray($user_data);
    $user->save();
    return 'OK';
  }
  // ユーザデータを取得する
  /**
     * @AmfReturnType("ArrayCollection")
     */
  public function getUserData() {
    $user_list = Doctrine::getTable('User')->getUserData();
    return $user_list;
  }
}

モデル


<?php
// lib/model/doctrine/UserTable.class.php
class UserTable extends Doctrine_Table
{
  public function getUserData() {
    $ret = array();
    $rec = $this->createQuery('u')
      ->execute();
    foreach ($rec as $user) {
      $ret[] = array($user->id, $user->name, $user->email, $user->phone);
    }
    return $ret;
  }
}

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

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


<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
           xmlns:s="library://ns.adobe.com/flex/spark"
           xmlns:mx="library://ns.adobe.com/flex/halo"
           minWidth="1024"
           minHeight="768"
           creationComplete="loadUserData()">
<fx:Script>
<![CDATA[
import mx.rpc.AsyncResponder;
import mx.rpc.AsyncToken;
import mx.collections.ArrayCollection;
import mx.automation.IAutomationObject;
import mx.controls.Alert;
import mx.rpc.remoting.RemoteObject;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
   
   	[Bindable]
private var userDataList:ArrayCollection;
   	private function loadUserData():void {
   		// サービスの呼び出し
   		var token:AsyncToken = remote.getUserData();
   		// ResultEventとFaultEventの処理を登録
        token.addResponder(new AsyncResponder(successLoadFunc, faultLoadFunc));
   	}
   
   	private function saveUserData():void {
   		// フォームで取得したデータを入れる配列
   		var data:Array = new Array();
   
   		data['name'] = nameForm.text;
   		data['email'] = emailForm.text;
   		data['phone'] = phoneForm.text;
   
   		// サービスの呼び出し
   		var token:AsyncToken = remote.saveUserData(data);
   		// ResultEventとFaultEventの処理を登録
   		token.addResponder(new AsyncResponder(successSaveFunc, faultSaveFunc));
   	}
   
   	private function successLoadFunc(e:ResultEvent,obj:Object = null):void {
// 明示的にキャストしないとエラーが出て、FlashBuilderさんがコンパイルしてくれません…
userDataList = ArrayCollection(e.result);
}
private function faultLoadFunc(e:FaultEvent,obj:Object=null):void{
Alert.show(e.toString(), "Error");
}
private function successSaveFunc(e:ResultEvent,obj:Object = null):void {
Alert.show(e.result.toString(), "Registerd");
// フォームをリセットして、データを再読み込みします。
resetUserData();
loadUserData();
}
private function faultSaveFunc(e:FaultEvent,obj:Object=null):void{
Alert.show(e.toString(), "Error");
}
private function resetUserData():void {
nameForm.text = "";
emailForm.text = "";
phoneForm.text = "";
}
]]>
</fx:Script>
<fx:Declarations>
<mx:RemoteObject 
id="remote"
endpoint="http://amf_sample/amfgateway/amf"
source="frontend.user.RegisterService"
destination="hoge" 
showBusyCursor="true"
/>
</fx:Declarations>
<mx:TabNavigator x="80" y="35" width="485" height="430">
<mx:Canvas label="save" width="100%" height="100%">
<s:Button x="80" y="270" label="Save" id="btnSaveUserData" click="saveUserData()"/>
<s:Button x="200" y="270" label="reset" id="btnResetUserData" click="resetUserData()"/>
<mx:Label x="50" y="40" text="Name"/>
<mx:Label x="50" y="120" text="Email"/>
<mx:Label x="50" y="200" text="Phone"/>
<s:TextInput x="150" y="35" id="nameForm" width="240"/>
<s:TextInput x="150" y="120" id="emailForm" width="240"/>
<s:TextInput x="150" y="200" id="phoneForm" width="240"/>
</mx:Canvas>
<mx:Canvas label="Load" width="100%" height="100%">
<mx:DataGrid x="20" y="20" height="340" width="450" dataProvider="{userDataList}">
<mx:columns>
<mx:DataGridColumn headerText="ID" dataField="0"/>
<mx:DataGridColumn headerText="Name" dataField="1"/>
<mx:DataGridColumn headerText="Email" dataField="2"/>
<mx:DataGridColumn headerText="Phone" dataField="3"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
</mx:TabNavigator>
</s:Application>

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

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

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

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

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

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

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

データを登録します。

保存成功。

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

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

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

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

前の記事へ

次の記事へ

一覧へ戻る

「その他」カテゴリの最新記事

PAGE TOP