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

今日は、Phalconのチュートリアル2のイベント管理から調べていきたいと思います。

イベント管理

EventsManagerは、私たちが特定の種類のイベントにリスナーを添付することができます。今私たちが興味のあるタイプは「dispatch」である。下記のコードは、ディスパッチャによって生成されたすべてのイベントをフィルタリングします。

<?php
$di->set('dispatcher', function() use ($di) {
//DIからの標準EventsManagerを取得
 $eventsManager = $di->getShared('eventsManager');
//セキュリティプラグインをインスタンス化
 $security = new Security($di);
//セキュリティプラグインを使用してディスパッチャで生産イベントをリッスン
 $eventsManager->attach('dispatch', $security);
$dispatcher = new Phalcon\Mvc\Dispatcher();
//ディスパッチャーにEventsManagerをバインド
 $dispatcher->setEventsManager($eventsManager);
return $dispatcher;
 });

イベント管理とは、プログラムの実行に際し、何らかのアクションが発生した際にプログラムに発信される信号(イベント)を受信し、そのイベントによって処理を振り分け、管理することです。

上記プログラムのでは、DIコンテナがEventsManagerを取得し、そのEventsManagerに、インスタンス化したセキュリティプラグイン(コンポーネント)を取り付け、最後にディスパッチャーにEventsManagerをセットしています。

セキュリティプラグインはapp/plugin/Security.phpに位置するクラスです。このクラスは、「beforeDispatch」メソッドを実装しています。これは、Dispatcherで生み出されるイベントの一つと同じ名前です。

<?php
use Phalcon\Events\Event,
 Phalcon\Mvc\User\Plugin,
 Phalcon\Mvc\Dispatcher,
 Phalcon\Acl;
class Security extends Plugin
 {
// ...
public function beforeDispatch(Event $event, Dispatcher $dispatcher)
 {
 // ...
 }
}

フックイベントは、常に生み出されるイベント($event)とイベント自体によって生成された第二のコンテキスト情報が含まれているオブジェクト($dispatcher)である最初のパラメータを受け取ります。プラグインがPhalcon\ MVC \User\Pluginクラスを拡張しますが、これは必須ではありません。しかし、これを行うことによって、彼らは、アプリケーション内で利用可能なサービスに簡単にアクセスすることができます。

今、我々は、ユーザがACLリストを使用してアクセスできるかどうかをチェックし、現在のセッションの役割を検証しています。ユーザーがアクセス権を持っていない場合は前に説明したように、ホーム画面にリダイレクトします。

<?php
use Phalcon\Events\Event,
 Phalcon\Mvc\User\Plugin,
 Phalcon\Mvc\Dispatcher,
 Phalcon\Acl;
class Security extends Plugin
{
// ...
public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher)
 {
//「 AUTH 」変数が積極的な役割を定義するために、セッション内に存在するかどうか確認してください
 $auth = $this->session->get('auth');
 if (!$auth) {
 $role = 'Guests';
 } else {
 $role = 'Users';
 }
//ディスパッチャからアクティブコントローラ/アクションを取る
 $controller = $dispatcher->getControllerName();
 $action = $dispatcher->getActionName();
//ACLリストを取得
 $acl = $this->getAcl();
//役割は、コントローラ(リソース)へのアクセスを持っているかどうかを確認してください
 $allowed = $acl->isAllowed($role, $controller, $action);
 if ($allowed != Acl::ALLOW) {
//彼がアクセス権を持っていない場合は、インデックスコントローラに彼を転送する
 $this->flash->error("You don't have access to this module");
 $dispatcher->forward(
 array(
 'controller' => 'index',
 'action' => 'index'
 )
 );
//我々は、現在の動作を停止させるようにディスパッチャ「false」をリターンする
 return false;
 }
}
}

ACLの提供

上の例では、$this->getAcl()メソッドによりACLを取得しています。この方法は、プラグインでも実装されています。今、私たちは、アクセス制御リスト(ACL)の構築方法を、ステップ·バイ·ステップで説明しようとしています。

<?php
//ACLの作成
$acl = new Phalcon\Acl\Adapter\Memory();
//デフォルトのアクションはアクセスを拒否します
$acl->setDefaultAction(Phalcon\Acl::DENY);
//登録ユーザーとアイデンティティを持たないゲストユーザの2つの役割を登録します
$roles = array(
 'users' => new Phalcon\Acl\Role('Users'),
 'guests' => new Phalcon\Acl\Role('Guests')
);
foreach ($roles as $role) {
 $acl->addRole($role);
}

ACLとは、アクセス制御リスト(Access Control List)と呼ばれ、オブジェクトに付属する許可属性のことです。コンピュータセキュリティにおけるアクセス制御を実現するために、あるリソースに対し、誰からどの操作を許可するかを列挙したものです。

上記プログラムでは、いったん全てのアクセスを拒否し、ユーザーごとのロールを登録し、そのロールごとにアクセスを許可するように作成しています。

今、私たちは、それぞれ各エリアのためのリソースを定義します。コントローラ名はresourcesであり、そのアクションはresourcesへのアクセスです。

<?php
//プライベートエリアリソース(バックエンド)
$privateResources = array(
 'companies' => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
 'products' => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
 'producttypes' => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
 'invoices' => array('index', 'profile')
);
foreach ($privateResources as $resource => $actions) {
 $acl->addResource(new Phalcon\Acl\Resource($resource), $actions);
}
//公共エリアリソース(フロントエンド)
$publicResources = array(
 'index' => array('index'),
 'about' => array('index'),
 'session' => array('index', 'register', 'start', 'end'),
 'contact' => array('index', 'send')
);
foreach ($publicResources as $resource => $actions) {
 $acl->addResource(new Phalcon\Acl\Resource($resource), $actions);
}

上記プログラムでは、プライベートリソースと公共リソースごとに、各コントローラのアクションを登録しています。つまり、プライベートリソースでは、CompaniesControllerのindexAction、searchAction、newAction、editAction、saveAction、ceateAction、deleteActionにアクセス許可を与えているということになります。

上記では、プライベートリソースと公共リソースのみがリストされていますが、これにAdminリソースとかを作成し、CompaniesControllerのdeleteActionは、Adminのみに許可を与えるなどということが行えるようになります。

ACLは現在、既存のコントローラとその関連アクションの知識を持っています。「Users」ロールは、「フロントエンド」と「バックエンド」の両方のすべてのリソースにアクセスできます。「Guest」ロールは、publicエリアにのみアクセスできます:

<?php
//ユーザーやゲストの両ロールへの公共エリアへのアクセス権を付与
foreach ($roles as $role) {
 foreach ($publicResources as $resource => $actions) {
 $acl->allow($role->getName(), $resource, '*');
 }
}
//ユーザーロールのみへのプライベートエリアへのアクセス権の付与
foreach ($privateResources as $resource => $actions) {
 foreach ($actions as $action) {
 $acl->allow('Users', $resource, $action);
 }
}

Userコンポーネント

すべてのUI要素とアプリケーションの視覚的なスタイルは、主にTwitter Bootstrapによって作成されています。アプリケーションの状態に応じて、ナビゲーションバーの変化のようないくつかの要素。例えば、右上隅にある、リンクは、ユーザーがアプリケーションにログインしている場合は、「サインアップ/ログイン」を「ログアウト」に変更します」。

このような部分は、アプリケーションのElementsコンポーネント(app/library/Elements.php)に実装されている「要素」です。

<?php
use Phalcon\Mvc\User\Component;
class Elements extends Component
{
public function getMenu()
 {
 //...
 }
public function getTabs()
 {
 //...
 }
}

このクラスは、Phalcon\Mvc\User\Componentを拡張します。それは、このクラスを使用してコンポーネントを拡張するのを強制されません。しかし、それはアプリケーションサービスにより迅速にアクセスを取得するのに役立ちます。今、我々はサービスコンテナにこのクラスを登録します。

<?php
//ユーザーコンポーネントを登録
$di->set('elements', function(){
 return new Elements();
});

ビュー内のコントローラ、プラグインやコンポーネントのように、このコンポーネントは、コンテナに、ちょうど以前に登録されたサービスと同じ名前の属性にアクセスすることで、登録されたサービスにアクセスする場合があります:

<div class="navbar navbar-fixed-top">
 <div class="navbar-inner">
 <div class="container">
 <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 </a>
 <a class="brand" href="#">INVO</a>
 <?php echo $this->elements->getMenu() ?>
 </div>
 </div>
</div>
<div class="container">
 <?php echo $this->getContent() ?>
 <hr>
 <footer>
 <p>&copy; Company 2012</p>
 </footer>
</div>

重要な箇所は、下記の部分です。

<?php echo $this->getContent() ?>

本日は以上です。

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

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

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

コメントをどうぞ

このページの先頭へ