Zend Framework では、デフォルトで提供されるクラス以外の選択肢も用意しています。 たとえばリクエストオブジェクト、ルータ、 そしてレスポンスオブジェクトなどについて別の選択肢があります。
Zend_Controller_Request_Http は、HTTP
環境で使用するリクエストオブジェクトです
Zend_Controller_Request_Http はデフォルトのリクエストクラスであり、
Zend_Controller_Dispatcher で用いられます。
Zend_Controller_Request_Http は、関連する値へのアクセスをカプセル化します。
たとえばコントローラやアクションルータの変数のキー名や値、
URI からパースした追加のパラメータの値などにアクセスできます。
Zend_Controller_Request_Http のプロキシとして動作することで、
スーパーグローバルの値にパブリックメンバとしてアクセスしたり、
現在のベース URL やリクエスト URI を管理することもできます。
スーパーグローバルの値はリクエストオブジェクトに設定することはできません。
そのかわりに setParam/getParam メソッドを使用して、
パラメータを設定あるいは取得します。
![]() |
スーバーグローバルデータ |
|---|---|
|
特定のスーパーグローバルにアクセスするには、
パブリックメソッドを使用する方法もあります。たとえば、
$_POST['user'] の値を取得するには、リクエストオブジェクト上で
getPost('user') をコールします。
Zend_Controller_Request_Http は、
サブディレクトリで Zend_Controller_Router_Rewrite を使用することができます。
Zend_Controller_Request_Http は自動的にベース URL を検出し、
それを適切に設定します。
たとえば、index.php をウェブサーバのサブディレクトリ
/projects/myapp/index.php においた場合は、ベース URL
(rewrite base) は /projects/myapp にしなければなりません。
マッチするルートを見つける前に、この文字列がパスの先頭から取り除かれます。
これにより、すべてのルートに余計な文字を追加する必要がなくなります。
ルート 'user/:username' は、
http://localhost/projects/myapp/user/martel および
http://example.com/user/martel の両方にマッチするようになります。
![]() |
URL の検出は大文字小文字を区別します |
|---|---|
自動的なベース URL の検出処理は大文字小文字を区別します。そのため、 URL とファイルシステムのサブディレクトリ名が確実に一致する必要があります (たとえ Windows マシンであっても同様です)。大文字小文字が一致しなかった場合は noRoute アクションがコールされます。 |
ベース URL の検出に失敗する場合は、
Zend_Controller_Request_Http クラス、あるいは
Zend_Controller_Front クラスの
setBaseUrl() メソッドを使用して
ベースパスを上書き指定することができます。
一番簡単な方法は Zend_Controller_Front で設定することです。
この設定はリクエストオブジェクトに引き継がれます。
独自のベース URL を設定する例を示します。
/**
* Zend_Controller_Front で独自のベース URL を指定することによるリクエストのディスパッチ
*/
$router = new Zend_Controller_Router_Rewrite();
$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('./application/controllers')
->setRouter($router)
->setBaseUrl('/projects/myapp'); // ベース URL を指定します!
$response = $controller->dispatch();
Zend_Controller_Router_Rewrite は、標準のルータです。
ルーティングとは、URI (ベース URL から取得した URI の一部)
を展開し、どのコントローラのどのアクションが
リクエストを処理するのかを決める処理のことです。
コントローラの値やアクション、そしてその他のパラメータが
Zend_Controller_Request_Http オブジェクトにまとめられます。
このオブジェクトを処理するのが Zend_Controller_Dispatcher_Standard です。
ルーティングが行われるのは一度だけ、すなわちリクエストを最初に受け取ってから
最初のコントローラに処理が渡される際だけです。
Zend_Controller_Router_Rewrite は、mod_rewrite 風の機能を
PHP だけで実現できるように設計されています。
この処理は Ruby on Rails のルーティングを多少参考にしており、
ウェブサーバの URL 書き換えに関する前提知識を必要としません。
以下の単純な mod_rewrite ルール (のいずれか) で動作するように設計されています。
RewriteEngine on RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
あるいは
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
Rewrite ルータを IIS ウェブサーバで使用するには Isapi_Rewrite を Isapi 拡張モジュールとしてインストールします。そして次のようなルールを記述します。
RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css)$)[\w\%]*$)? /index.php [I]
![]() |
IIS Isapi_Rewrite |
|---|---|
IIS を使用すると、 |
Lighttpd の場合は、次のようなルールを使用します。
url.rewrite-once = ( ".*\.(js|ico|gif|jpg|png|css)$" => "$0", "" => "/index.php")
Rewrite ルータを適切に使用するには、まずそのインスタンスを作成し、 次にユーザ定義のルーティングを追加し、それをコントローラに注入しなければなりません。 以下にコードの例を示します。
/* ルータを作成します */
$router = $ctrl->getRouter(); // デフォルトで rewrite ルータを返します
$router->addRoute(
'user',
new Zend_Controller_Router_Route('user/:username', array('controller' => 'user', 'action' => 'info'))
);
RewriteRouter で最も重要なのが、ユーザ定義のルーティングです。
これは、RewriteRouter の addRoute メソッドをコールして作成します。
このメソッドに、Zend_Controller_Router_Route
の新しいインスタンスを渡します。
$router->addRoute('user', new Zend_Controller_Router_Route('user/:username'));
最初のパラメータがこのルートの名前です。現在は多少冗長性が残ってしまっていますが、
将来は、URL ビューヘルパーの中でこれを使用し、ビュー内で簡単に
URL を生成できるようになる予定です。
ここで定義したルートを使用する方法も知っておく必要があるでしょう。
事前に定義したルートを取得するには、RewriteRouter の getRoute
メソッドを使用します。二番目のパラメータは、
Zend_Controller_Router_Route のインスタンスです。
Zend_Controller_Router_Route のコンストラクタの最初のパラメータは、
その URL に関連付けるルートです。
例えば、上の例で示したルートは http://example.com/user/martel
に対応します。ルート内のコロンは URL 変数を意味します。ルーティングに成功すると、
これらの変数は Zend_Controller_Request に注入されます。
その後は Zend_Controller_Request::getParam や
Zend_Controller_Action::_getParam メソッドでアクセスできるようになります。
今回の例では、username という名前のパラメータに
'martel' という値が設定されます。
![]() |
定義の順番 |
|---|---|
一番最後にマッチしたルートが適用されるので、 汎用的なルートは最初に定義するようにしましょう。 |
![]() |
許可される文字 |
|---|---|
現在の実装では、変数の識別子としてスラッシュ (/) 以外のあらゆる文字を使用可能ですが、できるだけ PHP の変数で使用可能な範囲の文字のみを使用することを強く推奨します。 この実装は将来変更される予定ですので、(PHP の変数で使用できない文字を用いていると) バグを引き起こす可能性があります。 |
ルートで使用される変数のうち、':controller' および ':action' のふたつは特別な扱いとなります。これらの特殊変数は、URL から コントローラとアクションを決定するために使用されます。 ':action' 変数は、そのルートあるいはデフォルトパラメータとして 常に定義されていなければなりません。 ':controller' 変数がもし定義されていない場合は、デフォルト値として IndexController が使用されます。
![]() |
特殊変数 |
|---|---|
これらの特殊変数の名前を変更することもできます。その場合は
|
$router->addRoute(
'user', new Zend_Controller_Router_Route(':controller/:action')
);
このルートが定義されているときにブラウザで
'http://example.com/news/latest' を選択すると、
Zend_Controller_Dispatcher は NewsController クラスの
latestAction を起動します。
ルートの中の変数には、すべてデフォルト値を設定することができます。
デフォルト値を設定するには、Zend_Controller_Router_Route
のコンストラクタの二番目のパラメータを使用します。
このパラメータは配列形式となります。配列のキーに変数名、
そのキーに対応する値としてデフォルト値を設定します。
$router->addRoute(
'archive', new Zend_Controller_Router_Route('archive/:year', array('year' => 2006))
);
ちょっとわかりにくいかもしれませんが、このルートは例えば 'http://example.com/archive/2005' および 'http://example.com/archive' にマッチします。後者の場合、変数 year の値は 2006 となります。
上の例は、単に year 変数の内容をリクエストに注入するだけのものです。 コントローラやアクションを設定していないので、ルーティングは行われません。 この例が使い物になるようにするには、 コントローラとアクションのデフォルト値を設定しなければなりません。
$router->addRoute(
'archive',
new Zend_Controller_Router_Route('archive/:year', array('year' => 2006, 'controller' => 'archive', 'action' => 'show')
);
このルートは、ArchiveController の showAction を実行します。
Zend_Controller_Router_Route に三番目のパラメータを追加し、
変数に関する制限事項を設定することができます。
この制限は、正規表現で設定します。
$router->addRoute(
'archive',
new Zend_Controller_Router_Route('archive/:year', array('year' => 2006), array('year' => '\d+'))
);
![]() |
ルートのマッチング |
|---|---|
Ruby on Rails とは異なり、ZF の RewriteRouter は 三番目のパラメータの制限を満たさない場合にもルートにマッチし、 デフォルト値を使用するようになっています。 そのため、URL 'http://example.com/archive/test' は上のルートにマッチし、 year は 2006 に設定されます。この機能は将来変更される予定で、 このマニュアルを書いている時点ではまだ議論中です。 |
Rewrite ルータはサブディレクトリ内でも使用可能です。
ベース URL の自動検出が Zend_Controller_Request_Http
によって行われます。
ベース URL の検出に失敗する場合は、
Zend_Controller_Request_Http のメソッド setBaseUrl()
を使用してベースパスを上書き指定することができます
(項7.4.2.3. 「ベース URL およびサブディレクトリ」 を参照ください)。
Zend_Controller_Router_Rewrite では、デフォルトのルートがひとつ事前に定義されています。
これは 'controller/action' 形式の URI にマッチします。
さらに、モジュール名を最初のパス要素として指定することができます。これにより、
'module/controller/action 形式の URI が使用できます。
また、URI に追加されたパラメータにもデフォルトでマッチします。
ルートがどのようにマッチするのか、例を見てみましょう。
// 以下のようになっているものとします
// $ctrl->setControllerDirectory(array(
// 'default' => '/path/to/default/controllers',
// 'news' => '/path/to/blog/controllers',
// 'blog' => '/path/to/blog/controllers'
// ));
モジュールのみ:
http://example/news
module == news
無効なモジュールとコントローラとの対応:
http://example/foo
controller == foo
モジュール + コントローラ:
http://example/blog/archive
module == blog
controller == archive
モジュール + コントローラ + アクション:
http://example/blog/archive/list
module == blog
controller == archive
action == list
モジュール + コントローラ + アクション + パラメータ:
http://example/blog/archive/list/sort/alpha/date/desc
module == blog
controller == archive
action == list
sort == alpha
date == desc
デフォルトのルータは、
Zend_Controller_Router_Route_Module
オブジェクトに何も設定せずに作成したインスタンスです。
// ルータ v1 との互換性のためのルート
$compat = new Zend_Controller_Router_Route_Module();
$this->addRoute('default', $compat);
![]() |
マッチする URI |
|---|---|
|
デフォルトのルートを使用したくない場合は、
removeDefaultRoutes() で削除します。
// 互換性のためのデフォルトルートを削除します $router->removeDefaultRoutes();
これまでの例では、すべて動的なルートを使用していました。 つまり、特定のパターンにマッチするものについてのルートです。 しかし、時には特定のルートを固定してしまい、 わざわざ正規表現エンジンを動かしたくない場合もあるでしょう。 そんなときには静的なルートを使用します。
$loginRoute = new Zend_Controller_Router_Route_Static('login', array('controller' => 'login', 'action' => 'form'));
$router->addRoute('login', $static);
新しいルートを追加する際に、
いちいちコードを書き換えるのではなく設定ファイルの変更で対応できると便利でしょう。
そんなときには addConfig() メソッドを使用します。基本的な使用法は、
まず Zend_Config 互換の設定を作成し、それをコードに読み込み、
そして RewriteRouter に渡すことです。
/** * サンプルの INI ファイル * routes.archive.route = "archive/:year/*" * routes.archive.defaults.controller = archive * routes.archive.defaults.action = show * routes.archive.defaults.year = 2000 * routes.archive.reqs.year = "\d+" * * routes.news.type = "Zend_Controller_Router_Route_Static" * routes.news.route = "news" * routes.news.defaults.controller = "news" * routes.news.defaults.action = "list" */ $config = new Zend_Config_Ini($file); $router = new Zend_Controller_Router_Rewrite(); $router->addConfig($config, 'routes');
上の例では、INI ファイルの 'routes' セクションを使用してルートを決めるよう、
ルータに指定しています。このセクションの第一レベルのキーがルート名に対応します。
上の例だと 'archive' と 'news' がこれにあたります。
ルートの各エントリには、最低限 'route' エントリとひとつ以上の 'defaults'
エントリが必要となります。また、オプションでひとつ以上の 'reqs'
('required' の略) も指定できます。ここで指定したものが、それぞれ
Zend_Controller_Router_Route_Interface
オブジェクトに対する引数となります。オプションのキー 'type' を使用すると、
特定のルートで使用するルートクラスの型を指定できます。デフォルトでは、これは
Zend_Controller_Router_Route となります。上の例では、
'news' ルートで
Zend_Controller_Router_Route_Static
を使用するようにしています。
Zend_Controller_Response_Http は、
HTTP 環境での使用に適したレスポンスオブジェクトです。
ヘッダの設定/取得/消去の機能があります。また、
__toString() メソッドを使用して、
レスポンス本体の前に全ヘッダを一括送信することもできます。
setHeader() は、二つの引数を受け取ります。
最初がヘッダの型で、次がヘッダの値です。三番目のオプションのパラメータを
true にすると、同じ型の既存のヘッダを強制的に上書きします。