この記事は、 Sencha Advent Calendar 2013 の8日目の記事です。
Sencha TouchでExt Directちゃんと使っていますか? いまだに、Ext.Ajax.requestなんかでやってないですよね?
今回は、Ext Directを利用する手順とNestedアクション対応です。
Ext Directを使おう
いまさら、Ext Directの説明をする必要はないでしょうが、ざっくりまとめるとExt Directとは、次のようになります。
1 2 |
クライアントのブラウザから擬似的にAjaxを利用して、サーバーサイドのクラスメソッドを呼び出すことができる、擬似RPC |
今回は、コンポーネントと連携させるわけではなく、純粋にサーバーサイドのメソッドを呼び出す手順までを紹介します。
ルーター設置
まず、ルーターが必要です。
Ext Directのリクエストは、すべてこのルーターに対してなげられます。 Ext.Ajax.requestのように、自分でなげさきのURLを毎回指定することはありません。 どのようなリクエストも、ルーターになげられるわけですが、そのときにサーバーサイドのどのメソッドを、どういった引数で実行してくれ!というったことがパラメーターで一緒になげられます。
ルーターは、このパラメーターを解析して、実行し正しくJSONを返す必要があります。
もちろん、このルーターを自作することもできますし、使い勝手のよいルーターをZEROから作ってもらってもかまいませんが、Senchaでは、
Ext.Direct Pack
とが提供されていて、これを使って実装することができます。
また、それぞれの言語や、フレームワークに対応したサードパーティー製のルーターも多数存在します。
http://www.sencha.com/forum/showthread.php?67992-Ext.Direct-Server-side-Stacks
Direct Packをダウンロードして解凍すると、各言語毎にディレクトリが分かれていますが、今回はPHPを利用します。 PHPディレクトリごと、ドキュメントルートに配置します。 もちろん、Sencha Cmdでワークスペースとアプリケーションはできあがっている前提ですよっ。
余談ですが、cacheディレクトリがあってそこにAPI定義をキャッシュするようになっているので、cache/api_cache.txtに書き込み権限をつけてあげてくださいね。
設置は、それでおわり。
プロバイダー登録
Direct Packには、api.phpとrouter.phpがあります。 api.phpをたたくと、サーバーサイドにどんなクラスとメソッドがあるかを返してくれます。
api.phpのルーターまでのURLを調整します。
1 2 |
$api->setRouterUrl('php/router.php'); // default |
“php/”を追加しました。
classesディレクトリにPHPクラスを配置して、api.phpでクラスメソッドを追加つれば、公開されるって仕組みですね。 まぁともかくこのapi.phpをindex.htmlが呼び出すように書き足します。
1 2 3 4 |
... <script id="microloader" type="text/javascript" src="php/api.php"></script> </head> |
PHPからは、下記のようなJavaScriptコードが出力されています。
1 2 |
Ext.ns('Ext.ss'); Ext.ss.APIDesc = {"url":"router.php","type":"remoting","actions":{"Echo":[{"name":"send","len":1}],"Exception":[{"name":"makeError","len":0}],"Time":[{"name":"get","len":0}],"File":[{"name":"list","len":1,"serverMethod":"listFiles"},{"name":"add","len":2,"formHandler":true}]},"namespace":"Ext.ss"}; |
定義だけあっても、利用はできません。 このExt.ss.APIDescに設定されている情報をクライアント側に登録する必要があります。
記述すべきは、app.jsです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Ext.application({ ... requires: [ 'Ext.direct.*', 'Ext.MessageBox' ], ... launch: function() { Ext.direct.Manager.addProvider(Ext.ss.APIDesc); // Destroy the #appLoadingIndicator element Ext.fly('appLoadingIndicator').destroy(); ... |
上記のように修正します。 requiresにExt.direct.*を追加し、launchで、Ext.ss.APIDescを登録します。 これで準備は完了です。
RPC利用
せっかく設定したので、実際に呼び出してみましょう。 本来アプリケーションの制御は、コントローラーに記述すべきですが、サンプルですのでコンポーネント内部で処理をします。
MyApp.view.Main(app/view/Main.js)に直接記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Ext.define('MyApp.view.Main', { ... config: { ... items: [ { ... items: [{ docked: 'top', xtype: 'titlebar', title: 'Welcome to Sencha Touch 2' }, { xtype: 'button', text: 'サーバーサイドメソッド実行', handler: function() { Ext.ss.Echo.send("サーバーに送信して、そのまま返ってくるメッセージ", function(msg) { alert(msg); }); } }], ... |
ボタンを一つ追加して、handlerに処理を記述します。
Ext.ss.APIDescで定義されたサーバーサイドのクラスメソッドは、プロバイダー登録が正常に終了する任意のオブジェクト下に、サーバーサイドと同じメソッド名の関数オブジェクトを生成します。 今回は、Ext.ssしたになります。
この生成オブジェクトをネームスペースと言います。
呼び出しを行うには、単純にクライアントサイドに生成されたメソッドを呼び出すだけですが、なんらかのコールバックが必要な場合は、引数+1個目にコールバック関数を設定することで、非同期処理実行後の任意処理を記述することができます。
また、このExt.ss.Echo.sendのことを、Direct関数といいます。(directFn)
Storeに対して設定したり、Formに対して設定することで、これらのコールバック処理さえも記述することなくデータを読み込んだり、送信したりすることができるよになります。
が、今回は長くなるので割愛します。
まとめ
- Ext Directを利用するには、ルーターが必要
- ルーター介してRPCを利用するには、サーバーサイドの側の公開メソッド仕様を取得し、プロバイダー登録する必要がある。
- プロバイダー登録が終われば、サーバーサイドと同じメソッド名の関数オブジェクト、指定された名前空間に生成される。
- 生成された関数オブジェクトをダイレクト関数という
- ダイレクト関数は、引数+1個目にコールバック関数を指定することができる。
Ext Directは、これ以外にも便利な機能がいっぱいありますが、今日紹介したように非常にシンプルな仕組みでもあります。 Ext JSでは、結構利用してもらえるようになってきたかなと思いますが、Sencha Touchでも使えますので、是非チャレンジしてみてください。
Ext.Ajax.requestによるURLの煩雑化を防ぐことができますし、実は自動的に通信の最適化も行われています。(コンバイン機能)
最初から、この設定して作るだけで通信処理がすっきりするなら、使わない手はないですよね。