フロントコントローラ
リクエストを受け取ったフロントコントローラ内では、まず受け取ったURIが解析され、最初に呼び出されるべきコントローラ名/アクション名/各種リクエストパラメータが取り出されます。この過程が「ルーティング」で、ルーティングを行うのがルータと呼ばれるものです。ルータによる出力はリクエストオブジェクトに格納され、ディスパッチャ(ディスパッチを行うための仕組み)に送られます。
ディスパッチャではリクエストオブジェクトに格納されているコントローラ名/アクション名/リクエストパラメータなどの情報を展開し、該当するアクションコントローラのインスタンスを作成して、最終的にアクションコントローラをコールします。
ルータとディスパッチャのどちらにおいてもコントローラ名/アクション名/リクエストパラメータが取り出されていますが、ルーティングは最初に1回だけ行われ、送られてきたリクエストURIの解析を行うものなのに対し、ディスパッチの方は送られてきたリクエストオブジェクトからの情報の展開を行います。つまり、URI解析(ルーティング)以降、リクエストオブジェクトに格納されている情報に対し何らかの操作がなされた場合には、それを読み込んで新たなコントローラ名/アクション名/リクエストパラメータを得るのはルータではなくディスパッチャだということです。
フロントコントローラにおける各処理の実際の記述
前回サンプルのフロントコントローラで使っていた「->run()
」は、下記を見ると分かるように3つの処理を行っています。
public static function run($controllerDirectory) { self::getInstance() ->setControllerDirectory($controllerDirectory) ->dispatch(); }
カスタマイズを特に行う必要がない場合はこちらの方が便利ですが、コントローラフォルダやオブジェクトなどを設定したい場合は、各処理を個別に記述する必要があるでしょう。
実際に個別の処理をフロントコントローラで記述すると次のようになります。
<?php require_once 'Zend/Controller/Front.php'; $front=Zend_Controller_Front::getInstance(); $front->setControllerDirectory('../application/controllers'); $front->dispatch();
各々の処理について解説していきます。
フロントコントローラのインスタンスを取得する「::getInstance()」
<?php $front = Zend_Controller_Front::getInstance();
まず、フロントコントローラを利用するためにインスタンスを取得する必要があります。このインスタンスは一つしか存在しないことになっています。これをシングルトンパターンといい、アプリケーションの総元締めとも言えるフロントコントローラの性格に合致したものとなっています。
コントローラフォルダを指定する「->setControllerDirectory()」
<?php
$front->setControllerDirectory('../application/controllers');
次に、アクションコントローラが格納されているフォルダを指定します。ここは配列を使用することで複数指定できます。また、既にコントローラフォルダが指定されているところへ新たに後から「->addControllerDirectory()
」で追加することも可能です。これらについては次回解説予定です。
->setControllerDirectory()
(あるいは->addControllerDirectory()
)」で複数のフォルダを指定するというのは、このような時に役立ちます。ディスパッチを行う「->dispatch()」
<?php $front->dispatch();
フロントコントーラのインスタンスが取得され、コントローラフォルダも決まると、後はディスパッチを行うのみです。
->dispatch()
」でルーティングとディスパッチ、さらには(ビューのレンダリングを行うかどうかは別として)レスポンスを返すところまでを行っています。 「->dispatch()
」ではリクエストオブジェクト/レスポンスオブジェクトを指定することができます。これはアプリケーションの開発過程において、単体テストで独自にリクエストを作成してアプリケーションの流れをテストするなどの場合に有用です。
<?php $front->dispatch(<リクエストオブジェクト>,<レスポンスオブジェクト>);
デフォルトはnullで、その場合、ディスパッチャはそれまでに登録されているリクエストオブジェクト/レスポンスオブジェクトを探し、それをディスパッチに使用します。なければその場でデフォルトのオブジェクトを作成し、ディスパッチに使用します。
ディスパッチについて
ここでディスパッチについて詳しく見ていきましょう。
ディスパッチの過程
ディスパッチの過程においては、以下の順序で処理が行われています。
- 情報を展開:
- インスタンスを作成:
- 実際にコール:
リクエストの再処理
ルータからリクエストオブジェクトを受け取ると、ディスパッチャは「リクエストが然るべきアクションに受け渡された」ことを示すフラグをセットします。このフラグはアクションコントローラや「preDispatch()
」「postDispatch()
」からリセットすることができます(後述)。
ディスパッチャのクラスについて
デフォルトでディスパッチャとして使用されるのはZend_Controller_Dispatcher_Standard
です。これは抽象クラスZend_Controller_Dispatcher_Abstract
を継承しています。もしアクションコントローラやアクションメソッドの命名規則を変える等、ディスパッチャの仕様を変更したい場合には、Zend_Controller_Dispatcher_Abstract
を継承しディスパッチャのサブクラスを作成することとなります。
環境にアクセスするためのメソッド
その他フロントコントローラでは、リクエスト処理中各環境にアクセスするためのメソッドが揃っています。以下の表に示します。
デフォルトの指定
メソッド | 概要 |
(set|get)DefaultControllerName() | コントローラ名のデフォルト(index)を指定/現設定を取得 |
(set|get)DefaultAction() | アクション名のデフォルト(index)を指定/取得 |
(set|get)BaseUrl() | ルーティング時にURLから取り除く基底URLを指定/取得 |
サブクラスを使用する際など、クラスも含めた各オブジェクトの指定
メソッド | 概要 |
(set|get)Request() | ディスパッチに用いるリクエスト・オブジェクトの指定/取得 |
(set|get)Router() | ディスパッチに用いるルータ・オブジェクトの指定/取得 |
(set|get)Dispatcher() | ディスパッチに用いるディスパッチャ・オブジェクトを指定/取得 |
(set|get)Response() | ディスパッチに用いるレスポンス・オブジェクトを指定/取得 |
プラグイン使用関連
メソッド | 概要 |
registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null) | プラグインオブジェクトを登録 |
unregisterPlugin($plugin) | プラグインオブジェクトを登録解除 |
例外発生処理関連
メソッド | 概要 |
throwExceptions($flag) | ディスパッチ時発生した例外のスローの有無を切り替え |
returnResponse($flag) | フロントコントローラがdispatch()からのレスポンスを返す(true)かレスポンスを自動的に発行する(false)かを切り替え。デフォルトはfalse。レスポンスの発行前に内容をチェックしたりログを取りたい場合などにtrueに設定する |
その他
メソッド | 概要 |
resetInstance() | 現在の設定を消去。主にテストに用いる |
パラメータをセットする
前回紹介した通り、フロントコントローラではパラメータをセットすることができます。これによりフロントコントローラにアプリケーションの設定情報を持たせてルータ/ディスパッチャ/アクションコントローラ内で使用することができます。ここで前回挙げたパラメータを扱うためのメソッドを再掲しておきます。
メソッド | 内容 |
setParam($name, $value) | パラメータ$nameの値を$valueに設定する |
getParam($name) | パラメータ$nameの値を得る |
setParams(array $params) | 連想配列$paramsにより複数のパラメータを設定する |
getParams() | すべてのパラメータの一覧を得る |
clearParams($name) | $nameを消去する |
ただし、ディスパッチの過程で使用するために事前に定義されているパラメータがあります。以下の表に示します。
パラメータ | 内容 |
disableOutputBuffering | trueにするとディスパッチャが出力をバッファリングせず、その場でレスポンスを行う。通常はfalse。一旦バッファリングしてから出力することで、必ずヘッダー部分が先に出力されるようになっている |
noErrorHandler | 例外処理を独自に行いたい場合など、trueで「ErrorHandler」プラグインを無効にする(ErrorHandlerについては後述) |
noViewRenderer | XMLやJSONなどHTML以外の出力をしたい場合や出力の必要がない場合など、trueで「ViewRenderer」アクションヘルパーを無効にする(Zend_Viewの回でも解説予定) |
useDefaultControllerAlways | trueで指定されたモジュール/コントローラ/アクションが存在しないリクエストのディスパッチ先をデフォルトコントローラにする(後述のエラーコントローラはそれ以外の例外処理にも適用される) |
サンプル
ここでちょっとしたサンプルを紹介します。フロントコントローラでデフォルトのコントローラ名とアクション名をそれぞれ「wings」「codezine」に変えてみます。
<?php require_once 'Zend/Controller/Front.php'; $front=Zend_Controller_Front::getInstance(); $front->setControllerDirectory('../zendapps/controllers'); $front->setDefaultControllerName('wings'); $front->setDefaultAction('codezine'); $front->dispatch();
「setDefaultControllerName('wings')
」と「setDefaultAction('codezine');
」でデフォルトのコントローラ名とアクション名を変えています。
もちろん、コントローラファイルは「WingsController.php」を用意します。「IndexController.php」は必要ありません。
<?php require_once 'Zend/Controller/Action.php'; require_once 'Zend/Date.php'; //Zend_Dateコンポーネントの呼び出し class WingsController extends Zend_Controller_Action { public function codezineAction() { $date=new Zend_Date; // (1) $this->view->assign('dt', $date->get(Zend_Date::TIMES)); // (2) } }
アクション・メソッドも「indexAction」はなく、「codezineAction」を定義しています。また、「codezineAction」中でビューに時刻を送るよう指定しています。ファイルの冒頭で呼び出している「Zend_Date」コンポーネントは日付・時刻を処理するためのコンポーネントで、(1) (2)で現在の時刻を取得しています(詳しくはZend_Dateの回で解説予定です)。ビューは「views/scripts/wings/codezine.phtml」を用意します。
以上で、「http://localhost」にアクセスするだけで「wings」アクションコントローラの「codezine」アクションメソッドが呼び出され、時刻が表示されているのが分かると思います。
$front->setDefaultControllerName('wings'); $front->setDefaultAction('codezine');