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ページの作り込みに入りたいと思います。