CakePHP2.2から利用できるようになったDispatcher Filterを利用して、Dispather時に動作環境の振り分けを行う仕組みを用意してみる

今まで環境に依存するような設定ファイルの切替はbootstrap.phpで処理していた。
でも、それだと1つのbootstrapファイルに複数環境の記述を記載するので、何かあった場合の影響範囲が広い問題があった。
そこで、CakePHP2.2以降から利用できるようになったDispatcher Filtersって機能があったのでこれを使ってみることにした。

Dispatcher Filtersはざっくり言うと、ディスパッチ処理の前後になんか処理を挟めるような機能で、詳しい説明は公式のドキュメント(Dispatcher Filters – CakePHP Cookbook v2.x documentation)を見た方がわかりやすい。

1. 振り分け用のbootstrapファイルを用意する

各環境別に利用したいbootstrapファイルを以下のように用意する
app
∟Config
 ∟Environment
  ∟development
   ∟bootstrap.php
  ∟stage
   ∟bootstrap.php
  ∟production
   ∟bootstrap.php

2. appディレクトリ配下にRouting/Filterディレクトリを用意する

用意後の構成はこんな感じ。
app
∟Routing
 ∟Filter

3. フィルター用のクラスを用意する

1.で作成したディレクトリにXXXFilter.phpというファイルを設置する。
(ここではEnvironmentFilter.phpとする)

app
∟Routing
 ∟Filter
  ∟EnvironmentFilter.php

4. フィルタリングの中身を記述する

2.で作成したファイルに、環境に依存する設定を環境別に用意したbootstrap.phpに振り分ける処理を記述

<?php
App::uses ('DispatcherFilter' , 'Routing' );

class EnvironmentFilter extends DispatcherFilter {
        /**
        * 優先度を設定。数字が大きいほど優先度が高い
        */
        public $priority = 12;
        /**
        * dispatch前に処理したいので、beforeDispatchに記述
        */
        public function beforeDispatch($event) {
              $serverName   = getenv('SERVER_NAME');
               if (preg_match('/^dev\.hoge\.co\.jp/' , $serverName)) {
                      // development environment
                     $boostrapDirectory = 'development';
              }
               elseif (preg_match('/^stage\.hoge\.co\.jp/' , $serverName)) {
                      // stage environment
                     $boostrapDirectory = 'stage';
              }
               else {
                      // production environment
                     $boostrapDirectory = 'production';
              }
              $bootstrapFilePath = APP . 'Config' . DS . 'Environment' . DS . $boostrapDirectory . DS . 'bootstrap.php' ;
               if (!file_exists($bootstrapFilePath)) {
                      throw new MissingDispatcherFilterException('boostreap file "' . $bootstrapFilePath . '" not exist. ');
              }
              define( 'ENVIRONMENT',$bootstrapFilePath);
       }
}

5. Dispatcher.filtersに設定を追加する

3.で作成したフィルターをDispatcher.filtersに追加して

Configure::write ('Dispatcher.filters' , array(
    'AssetDispatcher',
    'CacheDispatcher',
    'EnvironmentFilter',
));

これでdispatch前に環境依存の設定を読み込むことができるようになった。
この書き方だと、元のbootsrapに影響せずに各環境間の設定を対応することができるので、
保守性が上がりそう。
(まぁbootstrap内でif文を記述すれば同じようなことはできるのだけど、、)