onInit(array $args)ハンドラに渡されるページに必要なページ引数(array $args)や、initハンドラが使うサービス(オブジェクト)をインジェクトします。
ページ引数になるのは$_GET
、$POST
、$_SERVER
などのWebコンテキストや定数などです。ページを構成するのに必要な変数を揃えます。
例えば商品のIDが必要なページがあったとします。商品IDはクエリーでitemp.php?item_id=10のように渡されるとします。onInjectハンドラではこのように記述しページにその値を「注入」します。
public function onInject(array $args)
{
$itemId = $_GET['item_id'];
if (some_validate_func($itemId) {
// throw exception if validation failed
}
$this->injectArg('item_id', $itemId, $default);
}
$_GET
はよく使うのでGET
のみ専用のメソッドinjectGet()
があります。その他の引数はinjectArg()
を使います
$this->injectGet('item_id', 'id', $default);
※$GET['id']を$args['user_id']に
インジェクトした商品IDはonInitハンドラで利用できるようになります。
public function onInit(array $args)
{
$itemId = $args['item_id'];
...
onInitハンドラで使用するオブジェクトをページプロパティに代入します。 例えばOpen ID認証をする認証クラスApp_OpenIDクラスがあるとします。このように利用します。
/**
* @var App_Auth
*/
private $_auth;
public function onInit(array $args)
{
$_openId = BEAR::dependency('App_OpenID');
...
}
public function onInit(array $args)
{
$login = $this-> _openId->login($url);
...
}
ページを実行するMainクラスで、インジェクターの指定ができます。
$config = array('injector'=>'onTestInject');
BEAR_Main::run('Page_Index', $config);
デフォルトは"onInject"です。
onInitで$_GET
を読めば同じ事が実現できるのに、ページの引数として外部から注入してやるメリットはなんでしょうか?newして取得できるサービス(オブジェクト)をインジェクターからインスタンスとして渡すメリットはなんでしょうか?
大きなメリットは開発とテストです。$_GET
に依存するコードをonInit()で書いていたら、そのコードをテストするにはクエリーを付加して実行しないと動作しません。セッションに入っているデータなら、同じようにセッションにデータを入れて実行しないといけません。当たり前の事ですががこれがリモートサイトから取得するデータや、$_POST
のデータとかならそれを実行するための環境を揃えるのがなかなか大変です。
これがonInject()で必要なものを注入する方法だと、利用するところ(onInit)では用意されたものがダミーかオリジナルかにかかわりなく実装する事ができます。テストの時でもonInitでの変更が必要ありません。変更がないといことはテストが終わってもテストコードが利用するところに残る心配がありません。インジェクトする値の取得方法が変わっても、利用するところではテストが必要ないということでもあります。
デバックの時、用意されたものに問題があるのか、利用での問題なのか、といった切り分けは容易です。ページ引数は入り口が一本化してるのでログも取りやすくなります。FirePHP環境では常にインジェクトされた$argsが表示され、onInit()が正常に動く環境が整っているか簡単に確認できます。また必要な$argsキーを@requiredアノテーションでそのキーは必須なのだと記述することができます。例えば記事IDを用いて記事を表示するentry.php?id=1というページがあったとしましょう。クエリーなしでのアクセスは成り立たないので、@required idとアノテーションで記述するとそのクエリーがないアクセスは400(Bad Request)というステータスコード画面が出て終了します。
ページの利用権限(閲覧者、オーナー、管理者)などの権限や情報を外部から注入するというインジェクターを用意してページの機能の切り分けに使うということもできます。
セキュリティを考えてもパブリックな外部からのデータ(スーパーグローバル変数)を一カ所で精査でき、必要なものしか利用する場所に渡さないというのはメリットになります。