ルーティング
Fuel では、単純な静的なルート設定から HTTP の動詞によるルーティングを用いた高度なルート設定に至るまで、様々なルーティングが可能です。
ルート設定は、fuel/app/config/routes.php で行います。
予約済みルート
Fuel では次の4つの予約済みルート設定があります。_root_, _403_, _404_, _500_.
- _root_ - URI が指定されなかったときのデフォルトルート。
- _403_ - アプリケーションが投げた HttpNoAccessException がキャッチされなかったときに使われるルート。
- _404_ - アプリケーションが投げた HttpNotFoundException がキャッチされなかったときに使われるルート。
- _500_ - アプリケーションが投げた HttpServerErrorException がキャッチされなかったときに使われるルート。
リクエストした URI (ルーティング)がアプリケーション内で解決できないとき、 request クラスが HttpNotFoundException を投げます。
_404_ ルートが未定義の場合、フレームワーク自身のエラーハンドラを使って "page not found" メッセージが表示されます。 _403_ または _500_ ルートが未定義の場合、 これらの例外はキャッチされないまま、あなたのアプリケーションが投げる他の例外と同様に処理されます。
return array(
'_root_' => 'welcome/index',
'_404_' => 'welcome/404',
);
基本的なルーティング
左辺に記述されたルートは、リクエストされた URI と比較されます。もし一致していれば、そのリクエストは右辺の URI に経路づけられます。
このルーティングによって、次のようなことが可能になります。:
return array(
'about' => 'site/about',
'contact' => 'contact/form',
'admin' => 'admin/login',
);
やや高度なルーティング
ルート設定には正規表現を含めることが出来ます。 左辺とリクエストされた URI が一致したら、その一致した部分を右辺に代入するといったような、 左辺の正規表現による右辺の後方参照が利用可能です。また、次のようないくつかの特別な宣言があり、それを用いて何かに一致させたり、 あるいは特定セグメントに一致させたりすることが出来ます。
- :any - URI の任意の部分と一致、"何もない" には一致しない
- :everything - :any と同様、しかし "何もない" にも一致
- :segment - URI の 1 つのセグメントのみに一致、しかしそのセグメントは任意のものであっていい
- :num - 任意の数値と一致
- :alpha - UTF-8 を含む、任意のアルファベットと一致
- :alnum - UTF-8 を含む、任意のアルファベットや数字と一致
ここにいくつかの例があります。 :any と :everything の間の微妙な違いに注意:
return array(
'blog/(:any)' => 'blog/entry/$1', // /blog/entry_name が /blog/entry/entry_name に経路付けられ、
// /blog/ と一致します。 /blogging や /blog とは一致しません。
'blog(:any)' => 'blog/entry$1', // /blog/entry_name が /blog/entry/entry_name に経路付けられ、
// /blog/ や /blogging と一致します。 /blog とは一致しません。
'blog(:everything)' => 'blog/entry$1', // /blog/entry_name が /blog/entry/entry_name に経路付けられ、
// /blog/ 、 /blogging や /blog と一致します。
'(:segment)/about' => 'site/about/$1', // /en/about が /site/about/en に経路付けられる
'(\d{2})/about' => 'site/about/$1', // /12/about が /site/about/12 に経路付けられる
);
高度なルーティング
ルート設定では、名前付きパラメータを使えます。これより、URI セグメントに対して名前を与えることができ、 アクションメソッドの中でアクセスできます。
例:
return array(
'blog/:year/:month/:id' => 'blog/entry', // /blog/2010/11/entry_name が /blog/entry に経路付けられる
);
上の例では、/blog/2010/11/entry_name が捕捉され、 'blog' コントローラ内の 'entry' アクションにルーティングされます。 そこでは、下記のような名前付きパラメータを使うことができます。:
$this->param('year');
$this->param('month');
$this->param('id');
名前付きパラメータは正規表現で、後方参照として数えられることに注意しましょう。 例えば ':name/(\d{2})' において、2 桁の数字への後方参照は $2 であって、$1 ではありません。
HTTP の動詞によるルーティング
アクセスされた HTTP の動詞に基づいて、URL をコントローラとアクションに経路付けることができます。 このことによって、素早く簡単に RESTful なコントローラを作成できます。
例:
return array(
// GET /blog が /blog/all に、POST /blog が /blog/create に経路付けられる
'blog' => array(array('GET', new Route('blog/all')), array('POST', new Route('blog/create'))),
);
URL には、名前付きパラメータと正規表現を普通に使えます:
return array(
'blog/(:any)' => array(array('GET', new Route('blog/show/$1'))),
);
3 つめパラメータに false あるいは true を渡すことで、ルートが HTTP のみをサポートするのか、あるいは HTTPS のみをサポートするのかを指定することもできます。
// HTTPS のリクエストであった場合のみルートが有効になります
return array(
'blog/(:any)' => array(array('GET', new Route('blog/show/$1'), true)),
);
名前付きルートとリバースルーティング
リバースルーティングというのは、次のような考え方を指します。たとえば管理エリアを作ろうとし、そのルートをセットアップします。 ビューにおいて、管理エリアで例えば 'admin/start/overview' という HTML アンカーを使いたいとしましょう。 ところが、気が変わって、そのページを 'admin/overview' という風に変えることにします。 その結果、全てのビューで、そのリンクを更新しなければならなくなってしまいました...
名前付きルートとリバースルーティングを用いると、名前付きルートをアンカーリンクにすることができ、 ルートが変わっても、各ビューの中でのリンクはその変更を自動的に追随します。
ルートの例:
return array(
'admin/start/overview' => array('admin/overview', 'name' => 'admin_overview'), // admin/overview ページに対して名前付きルート名を追加する
);
アンカーの例:
// <a href="http://your_base_url/admin/start/overview">Overview</a> を生成する
echo Html::anchor(Router::get('admin_overview'), 'Overview');
今のところ、 app/config/routes.php に定義されているルートのみで動作することに注意しましょう。モジュールのルートでは動作しません。
インラインルート
ルートはコントローラのメソッドに解決される必要はありません。 FuelPHP はコントローラメソッドを置き換える Closure として定義される インラインルートもサポートします。コントローラのメソッドと同様にインラインルートは Response オブジェクト を返さなければなりません。 この Response オブジェクトは 自分で forge するか、 forge された Request を実行した結果として返します。
ルートの例:
return array(
'secret/mystuff' => function () {
// このルートは development 環境でのみ動作します
if (\Fuel::$env == \Fuel::DEVELOPMENT)
{
return \Request::forge('secret/mystuff/keepout', false)->execute();
}
else
{
throw new HttpNotFoundException('This page is only accessable in development.');
}
};
モジュールとルーティング
モジュールがどのようにルーティングを扱うか をお読みください。