FuelPHPを利用してログイン処理を実装する2

前回までに、Sencha Ext JSのfront/loginのページ、そしてそれをFuelPHPを通してローカルホストで実行するところまで、実装しました。今回は、Sencha Ext JSのloginページで、実際にFuelPHPを使ってログイン処理を実装します。
Ext Directを使う
Sencha Ext JSのページから何かしらサーバーサイドにリクエストを投げて、認証処理を実行する必要があります。ログインボタンを押した後に、JavaScriptを使って非同期通信を行い、これを実現します。JavaScriptで非同期通信を行うためには、Ajaxという、JavaScriptのHTTP通信機能を利用した通信を行うのが一般的です。Sencha Ext JSにも、この非同期通信を行うための便利なクラスが用意されています。
次のコードは、APIドキュメンテーションに記述されている、Ext.Ajaxクラスの例です。
| 1 2 3 4 5 6 7 8 9 10 11 12 | Ext.Ajax.request({      url: 'ajax_demo/sample.json',      success: function(response, opts) {          var obj = Ext.decode(response.responseText);          console.dir(obj);      },      failure: function(response, opts) {          console.log('server-side failure with status code ' + response.status);      }  }); | 
このように、非同期通信を行い、結果を取得してクライアントアプリケーションに結果を反映するやり方は、Sencha Ext JSに限ったことではありません。
しかしながら、Sencha Ext JSには、Ext Directというもっと便利な通信方式(正確には内部で非同期通信を行っていますが)が用意されています。
Ext Directってなんだ?
Ext Directの仕組み自体を説明すると、非常に長くなるため簡単に説明すると、サーバーサイドの関数やメソッドをJavaScriptから(擬似的に)呼び出すことができる というものです。
普通に考えて、クライアント側のJavaScriptから、サーバーサイドのクラスメソッドを呼び出すなんて不可能です。これを実現するために、Ext Directは、次の手順を行い利用を開始します。
- サーバーサイドにどのようなメソッドがあり、引数がいくつ渡せるのか?などのサーバーサイドの公開メソッド情報をJSONでクライアント側に定義する。
- Direct関数(クライアント側の)が呼び出された場合、サーバーサイドのルーターといわれる箇所(URL)に、実行したいサーバーサイドのメソッド情報を(引数など)送信する。
- ルーターが受け取った情報を解析して、サーバーサイドのメソッドを実行する。
- 実行結果をルーターが返す。
- クライアントサイドで、実行結果を受け取るコールバック関数で処理結果を受け取る。
クライアントサイドは、後述の手順を1つ行うだけで完了しますが、問題は、サーバーサイドです。 ルーターも自分で準備する必要があります。これがExt Directを導入するハードルになっているのも事実で、このルーターを作るのがめんどくさい。できてしまえば、通信処理の記述が完結になり、Sencha Ext JS側のソースコード量も減り良いことだらけです。
Ext Directの通信仕様は、Sencha のページに記載されていますので、興味がある人は覗いてみてください。
xenophy/fuel-ext-directを設置する
今回は、FuelPHPを使うと言うことは、何度も言っていますし、既に準備してもらっています。 FuelPHPでExt Directを使うためのパッケージが、世の中にあるのかなぁ〜と思って探ってみたら、意外と無くて、しょうが無いので作りました。
何か問題を見つけたらIssueでもください、暇見つけて対応するかもしれません。どちらにしても私自身が使っているので、問題があればアップデートします。
ます、FuelPHPのルートディレクトリに移動して、以下のコマンドを実行します。
| 1 | composer require xenophy/fuel-ext-direct | 
しばらくすると、FuelPHPのパッケージとしてダウンロードされ、設置されます。
composer.jsonに、”xenophy/fuel-ext-direct”: “^0.0.3” が追加され、fuel/packages/fuel-ext-direct ディレクトリ下にファイルが配置されます。
設置が完了したら、OrmAuth同様にfuel/app/config/config.php内に、fuel-ext-directをalways_loadに追加します。
| 1 2 3 4 5 6 7 | 'always_load'  => array(     'packages'  => array(         'orm',         'auth',         'fuel-ext-direct'     ), ) | 
設定ファイルもコピーしておきます。
fuel/packages/fuel-ext-direct/config/extdirect.php を fuel/app/config/extdirect.phpとしてコピーします。
urlの値を、ドキュメントルートのパスに書き換えてください。
| 1 2 3 4 5 | return array(     'url'               => '/~codex/direct',     'route'             => 'direct',     'classes_dirname'   => 'direct' ); | 
これで、Ext Directのルーターの設置は完了です。
Direct用クラスの実装
ルーターの設置を行ったので、今度はルーターが実行するDirect用のクラスを実装します。これは、xenophy/fuel-ext-directの設定に従います。
fuel/app/classes/directというディレクトリを作成して、login.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 | class Direct_Login {     /**      * Authentication      *      * @param $user      * @param $password      * @remotable      * @return array      */     function auth($user, $password) {         $result = array('success' => false);         // 認証処理         if (!Auth::login($user, $password)) {             $result['success'] = false;         } else {             $result['success'] = true;         }         return $result;     } } | 
fuel/app/classes/direct ディレクトリ下のクラスが公開対象ですが、クラスメソッドのドキュメントコメントに@remotableを指定すると公開されます。
Ext.direct.addProviderでAPIを登録する
作成した、fuel/app/classes/direct/login.phpのDirect_Loginクラスのauthメソッドを、Sencha Ext JS側から利用するために、Ext.direct.appProviderというメソッドで、Sencha Ext JS側に利用可能な状態を準備させます。
この設定は、login/app/Application.js内に記述します。
| 1 2 3 4 5 6 7 8 9 10 | requires: [     'Ext.direct.*' ], launch: function () {     // Ext.Directプロバイダー追加     Ext.direct.Manager.addProvider(Ext.REMOTING_API); }, | 
requiresに‘Ext.direct.‘***と追加して、launch**メソッドに、上記のコードを追加します。
ここで、Ext.REMOTING_API って初めて見ましたね、中身はJSON文字列なのですが、ここでサーバーサイドにどのようなメソッドが有り、引数が何個あるなどの情報を渡します。
このExt.REMOTING_APIは、自分で作成してもよいのですが、xenophy/fuel-ext-directが自動的に作成してくれますので、これを利用します。
| 1 | http://localhost/~codex/direct/api | 
にアクセスすると、以下の様なJSONが出力されます。
| 1 | var Ext = Ext || {}; Ext.REMOTING_API = {"url":"direct","type":"remoting","actions":{"Login":[{"name":"auth","len":2}]}}; | 
このJSONを利用します。このhttp://localhost/~codex/direct/apiをindex.phpに埋め込んでもよいのですが、その場合ユーザーがfrontやloginにアクセスする度に、このJSONを生成する処理がサーバーサイドで実行されてしまいます。
Sencha Cmdと連携して、JSONを埋め込んでしまう方法を紹介します。それは、app.jsonに、以下の設定を追加するだけで完了します。 本番環境等、URLが異なる場合は、JSにはき出してバンドルしてしまうのも手です。
| 1 2 3 4 5 6 7 8 9 10 | "js": [     {         "path": "http://localhost/~codex/direct/api",         "remote": true     },     {         "path": "app.js",         "bundle": true     } ], | 
front/loginともに記述しておくとよいでしょう。
ここまで、ローカルホストからSencha Ext JSのアプリケーションを実行したときに、Login.authという関数が、クライアントサイドから実行でき、実行するとサーバーサイドのDirect_Loginのauthメソッドを実行して、コールバック関数に処理結果を返してくれます。
ログイン処理を実装する
login/app/views/main/MainController.jsに以下を実装します。既に作成してあるonLoginを書き換えます。
| 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 | onLogin: function () {     var me = this,         v;     v = me.getView().down('mainform').getForm().getValues();     Login.auth(v.username, v.password, function (result) {         if (result.success === true) {             if (location.port === 80 || location.port === 443) {                 // リダイレクト                 location.href = '../';             } else {                 // リダイレクト for Sencha Cmd                 location.href = '../front/index.php';             }         } else {             // TODO: エラーメッセージ表示         }     }); } | 
ログインフォームのユーザー名、パスワードをLogin.authの引数に入れて、第三引数の関数オブジェクトでコールバック処理を行っています。
ここでは、ログインが成功した場合、frontにリダイレクトしていますが、jetty経由の場合(ポート番号が80、443じゃない場合)は、frontのディレクトリにリダイレクトしています。
ログイン認証を実装する
最後に、frontへアクセスしたときに、ログインしていなかったら、loginへリダイレクトする処理を実装します。
fuel/app/classes/controller/welcome.phpのaction_indexを以下の様に書き換えます。
| 1 2 3 4 5 6 7 8 | public function action_index() {     if (!Auth::check()) {         return Response::redirect('login/');     }     return Response::forge(View::forge('welcome/index')); } | 
ログイン認証は、OrmAuthのAuth::check()で行えます。ログインしている場合は、今まで通りfrontページを出力して、層で無い場合は、loginページにリダイレクトします。
おわりに
かなり駆け足で、作ってきたログイン処理もこれで終わりです。ログアウトは?リマインダーは?など、まだまだ本来のアプリケーションの場合、作り込む必要がありますね。さらに、OrmAuthの使い方もろくに説明しないまま、とりあえずコードを記述した感じできました。
とりあえず、いいんです。動けば。
次回から、ここまで、やってきた時に登場した項目を1つずつおさらいしながら掘り下げて行きたいと思います。そして、その次にfrontページの作り込みに入りたいと思います。

 
 
 
 
 
 
 
 
 
