Phalconのチュートリアル2(INVOアプリ)その1

今日から、何回かにわけてPhalconの公式サイトのチュートリアル2(INVOアプリ)について勉強していきたいと思います。

まず、Githubの下記のサイトからINVOアプリをダウンロードします。

Phalcon/invo

2015-04-02 16-59-11

解凍したフォルダ(invo-master)をinvoに名称変更して、C:\xampp/htdocsにコピーします。

NetBeansを起動したら、ファイル→新規プロジェクトで新規プロジェクトダイアログを開きます。

カテゴリ→PHP、プロジェクト→既存のリソースを使用するPHPアプリケーションと選択して、「次」ボタンをクリックします。

2015-04-02 17-05-25

ソースフォルダ→C:\xampp\htdocs\INVO、プロジェクト名→invo、PHPのバージョンPHP5.6と選択して、「次」ボタンをクリックします。

2015-04-02 17-08-15

実行方法→「ローカルWebサイト(ローカルWebサーバーで実行中)、プロジェクトURL→http://localhost/invo/と設定したら(デフォルトのまま)、終了ボタンをクリックします。

プロジェクト構造

これで、INVOプロジェクトが作成できました。最上位層には、4つのフォルダ(app、cache、public、schemas)があります。

2015-04-02 17-14-10

appフォルダには、MVC(models、views、controllers)以外に、config、forms、library、logs、pluginsフォルダがあります。

2015-04-02 17-17-58

トップページ

http;//localhost/invoでトップページを開いてみます。見たところレイアウト(CSS)はTwitter Bootstrapで作成されているようです。

2015-04-02 17-30-41

ルーティング

日本語に翻訳されていないので、Google先生に尋ねてみたのですが、下記のようにいまいち意味不明なので、読み飛ばすことにします。わかったのは、内蔵のルーターコンポーネントを使用しているということぐらいでしょうか。

INVOは内蔵されているルータコンポーネントで標準のルートを使用しています。/::コントローラ/:アクション/:paramsはこれらのルートには、次のパターンに一致する。これは、URIの最初の部分は、コントローラ、アクションと残りはパラメーターである第二であることを意味します。

次のルート/セッション/レジスタは、コントローラSessionControllerとそのアクションのRegisterActionを実行します。

設定

まず、最初にリクエストの入り口であるpublic/index.phpを開いてみてみたいと思います。

<?php
error_reporting(E_ALL);
use Phalcon\Mvc\Application;
use Phalcon\Config\Adapter\Ini as ConfigIni;
//$_GET['_url'] = '/contact/send';
//$_SERVER['REQUEST_METHOD'] = 'POST';
try {
define('APP_PATH', realpath('..') . '/');
/**
 * 環境設定の読み込み
 */
 $config = new ConfigIni(APP_PATH . 'app/config/config.ini');
/**
 * オートーローダー環境設定の読み込み
 */
 require APP_PATH . 'app/config/loader.php';
/**
 * アプリケーションサービスの読み込み
 */
 require APP_PATH . 'app/config/services.php';
$application = new Application($di);
echo $application->handle()->getContent();
} catch (Exception $e){
 echo $e->getMessage();
}

設定に関しては、Developer Toolsで自動生成されたindex.phpが設定ファイル自体を読み込んでいるのに対し、INVOアプリは、Iniクラス(コンポーネント)を使用して設定を読み込んでいるみたいです。

$config = new ConfigIni(APP_PATH . 'app/config/config.ini');

Iniコンポーネントによって読み込まれているconfig.iniファイルを開いてみてみます。

2015-04-02 17-54-50

データベースとアプリケーションのディレクトリ構造が設定されています。

config.iniの[database]項目のpassword = に、MySQLのパスワードを記述して、phpMyiAdminでinvoデータベースを作成することにします。

2015-04-02 18-01-36

オートローダー

app/config/loader.phpがオートローダーの環境設定みたいです。5つのフォルダが読み込まれています。

require APP_PATH . 'app/config/loader.php';

2015-04-02 18-07-46

コントローラー、プラグイン、ライブラリ、モデル、フォームの各フォルダを読み込んでいます。

 リクエストのハンドリング

この項目もいまいち意味不明なので、読み飛ばします。下記にGoogle先生の翻訳を掲載しておきます。

我々はファイルの末尾にスキップした場合、リクエストは最終的にPhalcon\Mvc \Applicationによって処理されたアプリケーションの実行をする必要があるものをすべて初期化し、実行する:

依存性の注入(DIコンテナ)

Laravelでも頻繁に出てきたので、なんとなくはわかっているのですが、この「依存性の注入」という単語は、未だになじめません。私は、「アプリケーションが必要としたときに、自動的にコンポーネントをインスタンス化して、提供してくれるサービスコンテナ」と理解しているのですが、間違っていたら指摘してください。もっとわかりやすい単語があればここで躓く人が減ると思うのですが。

公式サイトでは、app/config/sevice.phpのSessionコンポーネントが例として紹介されています。

app/config/service.phpの中のDIコンテナ(コンポーネントの集合)は、

require APP_PATH . 'app/config/services.php';

で、index.phpに読み込まれ、それぞれのコンポーネントが呼び出されるまで待機しています。

/**
 * Start the session the first time some component request the session service
 */
 $di->set('session', function() {
 $session = new SessionAdapter();
 $session->start();
 return $session;
 });

そして依存性を注入された(呼び出された)アプリケーションがインスタンス化され、コンテンツを処理(提供)します。

$application = new Application($di);
echo $application->handle()->getContent();

アプリケーションへのログイン

INVOアプリは、フロントエンドコントローラ(誰でも操作できるコントローラ)と、バックエンドコントローラ(ログインしたユーザーだけが操作できるコントローラ)を持っています。そして、バックエンドコントローラにログインするには、invoデータベースのusersテーブルにユーザー名とパスワードを持っているユーザーだけがログインできます。

INVOアプリケーションへのログイン操作をするためには、データベーステーブルが必要です。app/schemas/invo.sqlをphpMyAdminにインポートしたいと思います。

2015-04-02 21-33-09

5つのデータベースーブルが作成されました。

2015-04-02 21-35-39

usersテーブルを見てみます。デモユーザーが登録されています。usernameは、demo、パスワードは暗号化されていますので、不明です。

2015-04-02 21-48-26

早速、INVOアプリのLoginをクリックしてみましょう。ログインページには、既にデフォルトで、E-mailとパスワードが入力されています。おそらくこのままLoginボタンを押せば、ログインできるように作成されているのでしょう。

2015-04-02 21-52-15

予想通り、Loginボタンを押すだけで、ログインできました。と同時にInvoicesというメニューボタンが表示されています。

2015-04-02 21-58-30

ただ、このINVOアプリは、Productsタブをクリックすると、下記のようにエラーが表示されます。おそらく数字をバリデートするクラスだと思いますが、Numericalityクラスが見つからないといっています。この辺は、後日調べてみます。

2015-04-02 22-11-59

アプリケーションへのログイン、ログアウトを操作しているSessionControllerを下記に記述しておきます。どのような操作がなされているかをざっと目を通してみてください。

<?php
/**
 * SessionController
 *
 * ユーザーを認証することができます
 */
class SessionController extends ControllerBase
{
 public function initialize()
 {
 $this->tag->setTitle('Sign Up/Sign In');
 parent::initialize();
 }
public function indexAction()
 {
 if (!$this->request->isPost()) {
 $this->tag->setDefault('email', 'demo@phalconphp.com');
 $this->tag->setDefault('password', 'phalcon');
 }
 }
/**
 * セッションデータに認証されたユーザーを登録します
 *
 * @param Users $user
 */
 private function _registerSession(Users $user)
 {
 $this->session->set('auth', array(
 'id' => $user->id,
 'name' => $user->name
 ));
 }
/**
 * このアクションは認証とアプリケーションにユーザーを記録します
 *
 */
 public function startAction()
 {
 if ($this->request->isPost()) {
$email = $this->request->getPost('email');
 $password = $this->request->getPost('password');
$user = Users::findFirst(array(
 "(email = :email: OR username = :email:) AND password = :password: AND active = 'Y'",
 'bind' => array('email' => $email, 'password' => sha1($password))
 ));
 if ($user != false) {
 $this->_registerSession($user);
 $this->flash->success('Welcome ' . $user->name);
 return $this->forward('invoices/index');
 }
$this->flash->error('Wrong email/password');
 }
return $this->forward('session/index');
 }
/**
 * インデックスにアクティブなセッションのリダイレクトを終了します
 *
 * @return unknown
 */
 public function endAction()
 {
 $this->session->remove('auth');
 $this->flash->success('Goodbye!');
 return $this->forward('index/index');
 }
}

バックエンドのセキュリティ保護

バックエンドは、登録済みのユーザーのみがアクセス権を持っているプライベートエリアです。ユーザーが任意のコントローラーやアクションにアクセスしようとするたびにアクセスの可否を判定し、アクセス権のない場合は、一定のページへリダイレクトします。

その方法は、まず最初にDispatcherコンポーネントが呼び出され、リクエストがアプリケーションに何を要求しているかを判断します。そしてそのDispacherコンポーネントによってRootingコンポーネントに呼び出されたリクエストを知らせ、Rootingコンポーネントが適切なコントローラをロードし、対応するアクションを実行します。

通常、フレームワークが自動的にディスパッチャを作成します。このログイン機能に関していえば、ユーザーがアクセス権を持っているかどうかをアクションを実行する前に判断します。そして、下記のようにコンポーネントの代わりにブートストラップ(public/index.php)の中に作成しています。

$di->set('dispatcher', function() use ($di) {
$eventsManager = new EventsManager;
/**
 * Check if the user is allowed to access certain action using the SecurityPlugin
 */
 $eventsManager->attach('dispatch:beforeDispatch', new SecurityPlugin);
/**
 * Handle exceptions and not-found exceptions using NotFoundPlugin
 */
 $eventsManager->attach('dispatch:beforeException', new NotFoundPlugin);
$dispatcher = new Dispatcher;
 $dispatcher->setEventsManager($eventsManager);
return $dispatcher;
});

アプリケーションで使用されるディスパッチャは完全にコントロールすることができます。フレームワークトリガーイベント内の多くのコンポーネントは、操作の内部フローを変更できます。コンポーネントの接着剤としてのDIコンポーネントの行為として、EventManagerと呼ばれる新しいコンポーネントがあります。そのEventManagerによって、リスナーにイベントをルーティングしたり、コンポーネントによって生成イベントを中断したりすることができます。

本日は以上です。

このエントリーを含むはてなブックマーク Buzzurlにブックマーク livedoorクリップ Yahoo!ブックマークに登録

トラックバック&コメント

この投稿のトラックバックURL:

コメントをどうぞ

このページの先頭へ