1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20765 -->
4 <sect1 id="zend.controller.router" xmlns:xi="http://www.w3.org/2001/XInclude">
7 <sect2 id="zend.controller.router.introduction">
11 <classname>Zend_Controller_Router_Rewrite</classname> は、標準のルータです。
12 ルーティングとは、<acronym>URI</acronym> (ベース <acronym>URL</acronym> から取得した <acronym>URI</acronym> の一部)
13 を展開し、どのコントローラのどのアクションが
14 リクエストを処理するのかを決める処理のことです。
15 モジュールやコントローラ、アクション、そしてその他のパラメータが
16 <classname>Zend_Controller_Request_Http</classname> オブジェクトにまとめられます。
17 このオブジェクトを処理するのが <classname>Zend_Controller_Dispatcher_Standard</classname> です。
18 ルーティングが行われるのは一度だけ、すなわちリクエストを最初に受け取ってから
19 最初のコントローラに処理が渡される際だけです。
23 <classname>Zend_Controller_Router_Rewrite</classname> は、mod_rewrite 風の機能を
24 <acronym>PHP</acronym> だけで実現できるように設計されています。
25 この処理は Ruby on Rails のルーティングを多少参考にしており、
26 ウェブサーバの <acronym>URL</acronym> 書き換えに関する前提知識を必要としません。
27 以下の単純な mod_rewrite ルール (のいずれか) で動作するように設計されています。
30 <programlisting language="php"><![CDATA[
32 RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
39 <programlisting language="php"><![CDATA[
41 RewriteCond %{REQUEST_FILENAME} -s [OR]
42 RewriteCond %{REQUEST_FILENAME} -l [OR]
43 RewriteCond %{REQUEST_FILENAME} -d
44 RewriteRule ^.*$ - [NC,L]
45 RewriteRule ^.*$ index.php [NC,L]
49 Rewrite ルータを <acronym>IIS</acronym> ウェブサーバ (バージョン <= 7.0) で使用するには
50 <ulink url="http://www.isapirewrite.com">Isapi_Rewrite</ulink>
51 を Isapi 拡張モジュールとしてインストールします。そして次のようなルールを記述します。
54 <programlisting language="php"><![CDATA[
55 RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css|html)$)[\w\%]*$)? /index.php [I]
59 <title>IIS Isapi_Rewrite</title>
62 <acronym>IIS</acronym> を使用すると、<varname>$_SERVER['REQUEST_URI']</varname>
63 が存在しないか空の文字列に設定されます。このような場合、
64 <classname>Zend_Controller_Request_Http</classname> は
65 <varname>$_SERVER['HTTP_X_REWRITE_URL']</varname> の値を使用します。これは
66 <classname>Isapi_Rewrite</classname> 拡張モジュールが設定します。
71 <acronym>IIS</acronym> 7.0 ではネイティブの <acronym>URL</acronym> リライトモジュールが登場しました。
75 <programlisting language="xml"><![CDATA[
76 <?xml version="1.0" encoding="UTF-8"?>
81 <rule name="Imported Rule 1" stopProcessing="true">
83 <conditions logicalGrouping="MatchAny">
84 <add input="{REQUEST_FILENAME}"
85 matchType="IsFile" pattern=""
87 <add input="{REQUEST_FILENAME}"
88 matchType="IsDirectory"
89 pattern="" ignoreCase="false" />
91 <action type="None" />
93 <rule name="Imported Rule 2" stopProcessing="true">
95 <action type="Rewrite" url="index.php" />
104 Lighttpd の場合は、次のようなルールを使用します。
107 <programlisting language="lighttpd"><![CDATA[
109 ".*\?(.*)$" => "/index.php?$1",
110 ".*\.(js|ico|gif|jpg|png|css|html)$" => "$0",
116 <sect2 id="zend.controller.router.usage">
117 <title>ルータの使用法</title>
120 Rewrite ルータを適切に使用するには、まずそのインスタンスを作成し、
121 次にユーザ定義のルーティングを追加し、それをコントローラに注入しなければなりません。
125 <programlisting language="php"><![CDATA[
128 $router = $ctrl->getRouter(); // デフォルトで rewrite ルータを返します
131 new Zend_Controller_Router_Route('user/:username',
132 array('controller' => 'user',
138 <sect2 id="zend.controller.router.basic">
139 <title>基本的な RewriteRouter の操作法</title>
142 RewriteRouter で最も重要なのが、ユーザ定義のルーティングです。
143 これは、RewriteRouter の addRoute メソッドをコールして追加します。
144 このメソッドに、<classname>Zend_Controller_Router_Route_Interface</classname>
145 を実装したクラスの新しいインスタンスを渡します。
148 <programlisting language="php"><![CDATA[
149 $router->addRoute('user',
150 new Zend_Controller_Router_Route('user/:username'));
154 Rewrite ルータには、6 種類の基本的なルーティング方式があります
158 <itemizedlist mark="opencircle">
162 linkend="zend.controller.router.routes.standard">Zend_Controller_Router_Route</link>
169 linkend="zend.controller.router.routes.static">Zend_Controller_Router_Route_Static</link>
176 linkend="zend.controller.router.routes.regex">Zend_Controller_Router_Route_Regex</link>
183 linkend="zend.controller.router.routes.hostname">Zend_Controller_Router_Route_Hostname</link>
190 linkend="zend.controller.router.routes.chain">Zend_Controller_Router_Route_Chain</link>
197 linkend="zend.controller.router.default-routes">Zend_Controller_Router_Rewrite</link>
204 これらのルーティングは、チェインやユーザ定義のルーティング方式を作成する際に何度も使用します。
205 任意の設定でお好みの数のルーティングを使用できますが、
206 Module ルートだけは例外です。これを使用するのは一度だけで、
207 もっとも汎用的なルート (デフォルト) として使用します。
208 個々のルーティング方式については、後ほど詳細に説明します。
212 addRoute への最初のパラメータはルートの名前です。
213 これを使用して、ルータがルートを処理します。
214 たとえば <acronym>URL</acronym> の生成などに使用します。
215 二番目のパラメータはルート自身となります。
221 <classname>Zend_View</classname> の url ヘルパーです。
224 <programlisting language="php"><![CDATA[
226 "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
230 これは <filename>user/martel</filename> へのリンクとなります。
235 ルーティング処理は、定義されたすべてのルートから
236 リクエスト <acronym>URI</acronym> にマッチする定義を探すことによって行います。
237 マッチするものが見つかれば、ルートのインスタンスから変数の値が返され、
238 それを Zend_Controller_Request オブジェクトに注入します。
239 これを、後にディスパッチャやユーザが作成したコントローラで使用します。
240 マッチするものが見つからない場合は、チェイン内の次のルートを調べます。
245 <methodname>getCurrentRouteName()</methodname> メソッドを使用します。
246 これは、ルートをルータに登録する際に使用した識別子を返します。
247 ルートオブジェクトそのものを取得したい場合は
248 <methodname>getCurrentRoute()</methodname> を使用します。
254 一番最後にマッチしたルートが適用されるので、
255 汎用的なルートは最初に定義するようにしましょう。
262 ルーティングの結果返される値は、<acronym>URL</acronym> パラメータあるいは
263 ユーザ定義のルータのデフォルト値です。これらの値は、後ほど
264 <methodname>Zend_Controller_Request::getParam()</methodname> あるいは
265 <methodname>Zend_Controller_Action::_getParam()</methodname>
271 ルートで使用される変数のうち、'module'、'controller' および 'action'
272 の 3 つは特別な扱いとなります。これらの特殊変数は、<classname>Zend_Controller_Dispatcher</classname>
273 がディスパッチ先のコントローラとアクションを決定するために使用されます。
279 これらの特殊変数の名前を変更することもできます。その場合は
280 <classname>Zend_Controller_Request_Http</classname> の
281 <methodname>setControllerKey()</methodname> メソッドや
282 <methodname>setActionKey()</methodname> メソッドを使用します。
288 <sect2 id="zend.controller.router.default-routes">
289 <title>デフォルトのルート</title>
292 <classname>Zend_Controller_Router_Rewrite</classname> がデフォルトのルートとして設定されています。
293 これは <filename>controller/action</filename> 形式の <acronym>URI</acronym> にマッチします。
294 さらに、パス要素の最初の部分にモジュール名を指定できます。つまり
295 <filename>module/controller/action</filename> のような <acronym>URI</acronym> も可能です。
296 また、<acronym>URI</acronym> にパラメータを追加した形式、つまり
297 <filename>controller/action/var1/value1/var2/value2</filename>
298 のような <acronym>URI</acronym> にもデフォルトで対応しています。
302 ルータのマッチ処理についての例を示します。
305 <programlisting language="php"><![CDATA[
307 $ctrl->setControllerDirectory(
309 'default' => '/path/to/default/controllers',
310 'news' => '/path/to/news/controllers',
311 'blog' => '/path/to/blog/controllers'
319 無効なモジュール名は、コントローラ名として扱われます
324 http://example/blog/archive
326 controller == archive
328 モジュール + コントローラ + アクション
329 http://example/blog/archive/list
331 controller == archive
334 モジュール + コントローラ + アクション + パラメータ
335 http://example/blog/archive/list/sort/alpha/date/desc
337 controller == archive
344 デフォルトのルートは、<classname>Zend_Controller_Router_Route_Module</classname>
345 オブジェクトを 'default' という名前 (インデックス) で
346 RewriteRouter に保存したものです。
350 <programlisting language="php"><![CDATA[
351 $compat = new Zend_Controller_Router_Route_Module(array(),
354 $this->addRoute('default', $compat);
358 このデフォルトルートが不要な場合は、独自の 'デフォルト' ルートで上書きします
359 (つまり、'default' という名前で保存します)。
360 あるいは、<methodname>removeDefaultRoutes()</methodname>
364 <programlisting language="php"><![CDATA[
365 // すべてのデフォルトルートを削除します
366 $router->removeDefaultRoutes();
371 <sect2 id="zend.controller.router.rewritebase">
372 <title>ベース URL およびサブディレクトリ</title>
376 (例. <filename>http://domain.com/user/application-root/</filename>)
377 内でも使用可能です。この場合、アプリケーションのベース <acronym>URL</acronym>
378 (<filename>/user/application-root</filename>) の自動検出が
379 <classname>Zend_Controller_Request_Http</classname> によって行われ、適切に使用されます。
383 ベース <acronym>URL</acronym> の検出に失敗する場合は、
384 <classname>Zend_Controller_Request_Http</classname> のメソッド <methodname>setBaseUrl()</methodname>
386 (<link linkend="zend.controller.request.http.baseurl">ベース URL およびサブディレクトリ</link>を参照ください)。
389 <programlisting language="php"><![CDATA[
390 $request->setBaseUrl('/~user/application-root/');
395 <sect2 id="zend.controller.router.global.parameters">
396 <title>グローバルパラメータ</title>
399 グローバルパラメータをルータ内で設定できます。
400 これは <methodname>setGlobalParam()</methodname>
402 グローバルパラメータが設定されているにもかかわらず
404 ユーザが設定したパラメータのほうがグローバルパラメータより優先されます。
405 グローバルパラメータは、このように設定します。
408 <programlisting language="php"><![CDATA[
409 $router->setGlobalParam('lang', 'en');
413 <sect2 id="zend.controller.router.routes">
416 <xi:include href="Zend_Controller-Router-Route.xml" />
417 <xi:include href="Zend_Controller-Router-Route-Static.xml" />
418 <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
419 <xi:include href="Zend_Controller-Router-Route-Hostname.xml" />
420 <xi:include href="Zend_Controller-Router-Route-Chain.xml" />
421 <xi:include href="Zend_Controller-Router-Route-Rest.xml" />
424 <sect2 id="zend.controller.router.add-config">
425 <title>RewriteRouter での Zend_Config の使用法</title>
429 いちいちコードを書き換えるのではなく設定ファイルの変更で対応できると便利でしょう。
430 そんなときには <methodname>addConfig()</methodname> メソッドを使用します。基本的な使用法は、
431 まず <classname>Zend_Config</classname> 互換の設定を作成し、それをコードに読み込み、
432 そして RewriteRouter に渡すことです。
436 例として、次のような <acronym>INI</acronym> ファイルを考えてみましょう。
439 <programlisting language="php"><![CDATA[
441 routes.archive.route = "archive/:year/*"
442 routes.archive.defaults.controller = archive
443 routes.archive.defaults.action = show
444 routes.archive.defaults.year = 2000
445 routes.archive.reqs.year = "\d+"
447 routes.news.type = "Zend_Controller_Router_Route_Static"
448 routes.news.route = "news"
449 routes.news.defaults.controller = "news"
450 routes.news.defaults.action = "list"
452 routes.archive.type = "Zend_Controller_Router_Route_Regex"
453 routes.archive.route = "archive/(\d+)"
454 routes.archive.defaults.controller = "archive"
455 routes.archive.defaults.action = "show"
456 routes.archive.map.1 = "year"
457 ; あるいは: routes.archive.map.year = 1
461 上の <acronym>INI</acronym> ファイルを、次のようにして
462 <classname>Zend_Config</classname> オブジェクトに読み込みます。
465 <programlisting language="php"><![CDATA[
466 $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
467 $router = new Zend_Controller_Router_Rewrite();
468 $router->addConfig($config, 'routes');
472 上の例では、<acronym>INI</acronym> ファイルの 'routes' セクションを使用してルートを決めるよう、
473 ルータに指定しています。このセクションの第一レベルのキーがルート名に対応します。
474 上の例だと 'archive' と 'news' がこれにあたります。
475 ルートの各エントリには、最低限 'route' エントリとひとつ以上の 'defaults'
476 エントリが必要となります。また、オプションでひとつ以上の 'reqs'
477 ('required' の略) も指定できます。ここで指定したものが、それぞれ
478 <classname>Zend_Controller_Router_Route_Interface</classname>
479 オブジェクトに対する引数となります。オプションのキー 'type' を使用すると、
480 特定のルートで使用するルートクラスの型を指定できます。デフォルトでは、これは
481 <classname>Zend_Controller_Router_Route</classname> となります。上の例では、
483 <classname>Zend_Controller_Router_Route_Static</classname>
488 <sect2 id="zend.controller.router.subclassing">
489 <title>ルータのサブクラスの作成</title>
492 標準の rewrite ルータには、必要となるであろう機能のほとんどが組み込まれています。
493 もし新しいルータ型を作成する必要があるとすれば、
494 それは既存のルートに対して新しい機能を追加したり機能を変更したりしたい場合くらいでしょう。
498 どこかで、既存のものとはまったく異なるルーティング処理が必要となったとしましょう。
499 そんな場合には <classname>Zend_Controller_Router_Interface</classname>
500 を使用します。これは、ルータとして最低限必要なひとつのメソッドのみを定義したインターフェイスです。
503 <programlisting language="php"><![CDATA[
504 interface Zend_Controller_Router_Interface
507 * @param Zend_Controller_Request_Abstract $request
508 * @throws Zend_Controller_Router_Exception
509 * @return Zend_Controller_Request_Abstract
511 public function route(Zend_Controller_Request_Abstract $request);
516 ルーティング処理は、システムが最初にリクエストを受け取った際に一度だけ行われます。
517 ルータの役割は、リクエストの内容に応じてコントローラやアクションとオプションパラメータを決定し、
519 その後、リクエストオブジェクトがディスパッチャに渡されます。
520 ルートに対応するディスパッチトークンがない場合は、ルータは何も行いません。