ルータ
フロントコントローラにおいて、最初に実行されるのがルーティングです。ここではルーティングについてその仕組みと設定方法について見ていきます。
前回、ルーティングについて「ルーティングは最初に1回だけ行われ、送られてきたリクエストURIの解析を行う」と述べましたが、通常それほど意識しないかもしれません。ルーティングは特に設定しない限り、デフォルトの方式で行われます。第2回で紹介したURIのパターンは、このデフォルトのルーティングです。
例えばよくディスパッチされる特定のモジュール・コントローラ・アクション・パラメータがある時など、URLが長くなってしまったり、あるいはそれらを見せたくない場合に、ルーティングの変更により、好みのURL記述で該当アクションへのディスパッチすることが可能になります。
ルーティング設定の基本
ルーティングを設定する場合は、フロントコントローラ内で次のようにします。
$router=$front->getRouter(); $router->addRoute('myrouting', new Zend_Controller_Router_Route(<ルーティング方式>));
「getRouter()
」でルータを作成します。これは標準のルータであるZend_Controller_Router_Rewrite
のインスタンスです。これに「addRoute()
」でルーティングの方式を追加していきます。「addRoute()
」の第1引数はルーティングのラベル(名前は任意です)で、第2引数でルーティング方式の指定を行います。
ここで言うルーティング方式とは、送られてきたURI文字列を解釈してモジュール/コントローラ/アクション/パラメータを決定する――すなわち、ルーティングを行うための解釈のルールのことです。同じURIが送られてきても、それをどう解釈するかによって送られるべきコントローラやアクションなどが異なってきます。
第2引数では複数のルーティング方式を追加でき、実際のルーティングでは追加順にチェックがなされます。最後にマッチした(マッチした方式の中では最も後に追加された)ルーティング方式が適用されます。
ルーティングの型
さて、ルーティングの方式を追加するところまでは触れましたが、「addRoute()
」の第2引数で指定する実際のルーティング方式はどのように定義するのでしょうか。
標準的なルーティングの型
標準的なルーティング方式設定は、Zend_Controller_Router_Route
クラスのコンストラクタで行います。コンストラクタには3つの引数があります。
$route = new Zend_Controller_Router_Route(
<ルートの定義>,
<デフォルト値>,
<正規表現による変数の制限>
);
(1)第1引数:ルートの定義
ルートとは、ルーティング方式にマッチする特定のURI記述のことです。4つの要素で構成されます。
要素 | 内容 |
/ | 区切り |
name | 名前(静的な要素) |
:name | パラメータ(動的な要素) |
* | ワイルドカード |
例えば
'cz/:id',
は、「http://~/cz/<idパラメータ>」がマッチします。
これにマッチする文字列が送られてくれば(さらに後述する第3引数での変数の制限もクリアすれば)、ここで指定されるルーティング方式でルーティングされることになります。しかし上記の場合定義に「:controller」(コントローラ名)や「:action」(アクション名)が入っておらず、ディスパッチされるコントローラやアクションは決定されていません。このような文字列でも、第2引数でコントローラやアクションのデフォルト値を設定することでディスパッチ先を指定することができます(そこでも指定がなければ、フロントコントローラレベルで設定されているデフォルトのコントローラ/アクションへディスパッチされるでしょう)。
(2)第2引数:デフォルト値
配列で定義します。第1引数で触れなかった値も設定できます。例えば
array( 'controller' => 'wings', 'action' => 'codezine', 'id' => 7 )
で、パラメータ「controller」「action」「id」のデフォルトはそれぞれwings、codezine、7に設定されます。
Zend_Controller_Request::getParam()
やZend_Controller_Action::_getParam()
でアクセスすることが可能です。また、モジュール名/コントローラ名/アクション名を格納しているパラメータ名は、それぞれ「module」「controller」「action」ですが、変更することもできます。Zend_Controller_Request_HTTPのsetControllerKey(<パラメータ名>)
やsetActionKey(<パラメータ名>)
で行えます。(3)第3引数:正規表現による変数の制限
パラメータが整数であってほしい場合など、正規表現で変数のパターンを制限することができます。例えばid
パラメータを整数に絞りたい場合は、
array('id' => '\d+')
とします。
以上を用いたサンプルを後ほど示します。
特殊なルーティング
以下の場合は、専用のクラスがあります。
(1)静的な要素のみのルーティング
動的な要素がない場合は、Zend_Controller_Router_Route_Static
を用います。これで不要に正規表現エンジンを動かさずに済む分、ルーティングが高速になるというメリットがあります。下記では、「http://~/whatsnew」に対しlogコントローラのwhatsnewアクションが設定されます。
$router->addRoute('myrouting', new Zend_Controller_Router_Route_Static( 'whatsnew', array('controller' => 'log', 'action' => 'whatsnew') ));
(2)正規表現を用いたルーティング方式の指定
Zend_Controller_Router_Route_Regexで、正規表現を使ってルーティング方式を指定できます。これを用いると、複雑にはなりますが、高速かつ、標準のルーティング設定では不可能な柔軟性のあるルーティングが実現できます。
$route = new Zend_Controller_Router_Route_Regex(
<URL正規表現>,
<デフォルト(連想配列)>,
<正規表現サブパターンとパラメータ名のキー>,
<urlヘルパー用の逆のURL表記>)
第1引数で、正規表現を使いURLを表現します。こちらでマッチしたサブパターンをパラメータとして使う場合、マッチした順に連想配列のキーとして「1」「2」…が割り当てられます(これらは文字列「'1'」「'2'」ではなく数値「1」「2」です)。つまり次のような定義の場合、
new Zend_Controller_Router_Route_Regex( 'w-codezine(\d+)\.html', array( 'controller' => 'wings', 'action' => 'codezine' ) )
「controller」には「wings」が、「action」には「codezine」が、「1」には第1引数の「(\d+)」でマッチしたパラメータが入り、リクエストオブジェクトに送られます。第2引数では「Zend_Controller_Router_Route
」同様にデフォルト値を指定します。
第3引数ではマッチした数値キーにパラメータ名を割り当てることができ、後に参照しやすくします。第4引数はZend_ViewのurlヘルパーでURL文字列を作成するために使用するreverse URLをsprintf()
方式の文字列で指定します。例えば、第1引数が上記の通り「'w-codezine(\d+)\.html'」の場合は、「w-codezine%d.html」になります。
その他、次のようなルールがあります。
- 「^(行頭)」「$(行末)」は正規表現に自動的に付加される
- URIの先頭・末尾の「/」は除かれて判断される。「http://~/mycontroller/myaction/」は「mycontroller/myaction」がマッチする
- 正規表現の区切り記号に「#」が使用されているので、表現中に「#」がある場合はエスケープする必要がある。
$this->_regex = '#^' . $route . '$#i';