ルーティングは URL とコントローラーのアクションをマップするツールを提供します。 ルートを設定することで、アプリケーションの実装方法を URL の構造から分離できます。
CakePHP でのルーティングはまた パラメーターの配列を URL 文字列に変換する リバースルーティングというアイディアも含まれます。リバースルーティングを使用することによって、 アプリケーションの URL の構造を全部のコードの書き直しをせずに再調整できます。
ここでは、 CakePHP の最も一般的なルーティングの方法について例を出して説明します。 ランディングページとして何かを表示したい時がよくあるでしょう。そのときは、 routes.php ファイルに以下を加えます。
use Cake\Routing\Router;
// スコープ付きルートビルダーを使用。
Router::scope('/', function ($routes) {
$routes->connect('/', ['controller' => 'Articles', 'action' => 'index']);
});
// static メソッドを使用。
Router::connect('/', ['controller' => 'Articles', 'action' => 'index']);
Router
はルーティングするための2つのインターフェースを提供します。
この static メソッドは後方互換性のあるインターフェースですが、
スコープ付きビルダーで複数のルートを構築するためのより簡潔な構文を提供し、
パフォーマンスは向上します。
これはサイトのホームページにアクセスした時に ArticlesController
の
index メソッドを実行します。時々、複数のパラメーターを受け取る動的なルートが
必要になると思います。それが必要になるケースは、例えば、記事の内容を表示するためのルートです。
$routes->connect('/articles/*', ['controller' => 'Articles', 'action' => 'view']);
上記のルートは、 /articles/15
のような URL を受け取り、 ArticlesController
の view(15)
メソッドを呼びます。しかし、これは /articles/foobar
のような URL からの
アクセスを防ぐわけではありません。もし、あなたが望むなら、いくつかのパラメーターを正規表現に従うように
制限することができます。
$routes->connect(
'/articles/:id',
['controller' => 'Articles', 'action' => 'view']
)
->setPatterns(['id' => '\d+'])
->setPass(['id']);
// 3.5 より前はオプション配列を使用
$routes->connect(
'/articles/:id',
['controller' => 'Articles', 'action' => 'view'],
['id' => '\d+', 'pass' => ['id']]
);
上の例はスターマッチャーを新たにプレースホルダー :id
に変更しました。
プレースホルダーを使うことで、URL 部分のバリデーションができます。
このケースでは \d+
という正規表現を使いました。なので、数字のみが一致します。
最後に、 Router に id
プレースホルダーを view()
関数の引数として渡すように
pass
オプションで伝えます。このオプションの詳細は後で説明します。
CakePHP の Router はルートを逆にできます。それは、一致するパラメーターを含む配列から、 URL 文字列を生成できることを意味します。
use Cake\Routing\Router;
echo Router::url(['controller' => 'Articles', 'action' => 'view', 'id' => 15]);
// 出力結果
/articles/15
ルートは一意の名前を付けることもできます。これは、リンクを構築する際に、 ルーティングパラメーターをそれぞれ指定する代わりに、ルートを素早く参照することができます。
// routes.php の中で
$routes->connect(
'/login',
['controller' => 'Users', 'action' => 'login'],
['_name' => 'login']
);
use Cake\Routing\Router;
echo Router::url(['_name' => 'login']);
// 出力結果
/login
ルーティングコードを DRY に保つために、Router は 'スコープ' (scopes) というコンセプトを 持っています。スコープは一般的なパスセグメントを定義し、オプションとして、デフォルトに ルーティングします。すべてのスコープの内側に接続されているルートは、ラップしているスコープの パスとデフォルトを継承します。
Router::scope('/blog', ['plugin' => 'Blog'], function ($routes) {
$routes->connect('/', ['controller' => 'Articles']);
});
上記のルートは /blog/
と一致し、それを
Blog\Controller\ArticlesController::index()
に送ります。
アプリケーションの雛形は、いくつかのルートをはじめから持った状態で作られます。 一度自分でルートを追加したら、デフォルトルートが必要ない場合は除去できます。
コードを DRY に保つために 'ルーティングスコープ' を使用してください。
ルーティングスコープはコードを DRY に保つためだけではなく、Router の操作を最適化します。
このメソッドは /
スコープがデフォルトです。スコープを作成しいくつかのルートを
接続するために、 scope()
メソッドを使います。
// config/routes.php 内で、
use Cake\Routing\Route\DashedRoute;
Router::scope('/', function ($routes) {
// 標準のフォールバックルートを接続します。
$routes->fallbacks(DashedRoute::class);
});
connect()
メソッドは3つのパラメーターを持ちます。あなたが一致させたい URL テンプレート、
ルート要素のためのデフォルト値、そしてルートのためのオプションの3つです。
しばしば、オプションには、ルーターが URL の要素を一致することに役立つ
正規表現ルールが含まれます。
ルートを定義するための基本のフォーマットは、次の通りです。
$routes->connect(
'/url/template',
['targetKey' => 'targetValue'],
['option' => 'matchingRegex']
);
1番目のパラメーターは、Router にどの URL を制御しようとしているのか伝えます。この URL は 普通のスラッシュで区切られた文字列ですが、ワイルドカード (*) や ルート要素 を含むことができます。ワイルドカードは、すべての引数を受け付けることを意味します。 * なしだと、文字列に完全一致するものだけに絞られます。
URL が特定されたら、一致したときにどのような動作をするかを CakePHP に伝えるために
connect()
の残り2つのパラメーターを使います。2番目のパラメーターは、ルートの
'ターゲット' を定義します。 これは、配列または行先の文字列として定義できます。
ルートターゲットの例をいくつか示します。
// アプリケーションのコントローラーへの配列ターゲット
$routes->connect(
'/users/view/*',
['controller' => 'Users', 'action' => 'view']
);
// アプリケーションのコントローラーへの文字列ターゲット。 3.6.0 以上が必要
$routes->connect('/users/view/*', 'Users::view');
// プレフィックス付きのプラグインコントローラーへの配列ターゲット
$routes->connect(
'/admin/cms/articles',
['prefix' => 'admin', 'plugin' => 'Cms', 'controller' => 'Articles', 'action' => 'index']
);
// プレフィックス付きのプラグインコントローラーへの文字列ターゲット。3.6.0 以上が必要
$routes->connect('/admin/cms/articles', 'Cms.Admin/Articles::index');
接続する最初のルートは、 /users/view
から始まる URL と一致し、
それらのリクエストを UsersController->view()
にマップします。
末尾の /*
は、メソッド引数として追加の部分を渡すようにルーターに指示します。
例えば、 /users/view/123
は、 UsersController->view(123)
にマップされます。
上記は文字列ターゲットの例を示しています。文字列ターゲットは、 ルートの宛先をコンパクトに定義する方法を提供します。 文字列ターゲットの構文は次のとおりです。
[Plugin].[Prefix]/[Controller]::[action]
いくつかの文字列ターゲットの例です。
// アプリケーションのコントローラー
'Bookmarks::view'
// プレフィックス付きのアプリケーションコントローラー
Admin/Bookmarks::view
// プラグインのコントローラー
Cms.Articles::edit
// プレフィックス付きのプラグインコントローラー
Vendor/Cms.Management/Admin/Articles::view
バージョン 3.6.0 で追加: 文字列ベースのルートターゲットが追加されました。
先ほど、パスの追加の部分を取り込むために貧欲なスター (greedy star) /*
を使用していましたが、
/**
流れ星 (trailing star) もあります。2つのアスタリスクをつなげると、
URL の残りを1つの引数として取り込みます。これは、 /
を含む引数を使用したい時に便利です。
$routes->connect(
'/pages/**',
['controller' => 'Pages', 'action' => 'show']
);
/pages/the-example-/-and-proof
が URL として渡ってきたときに、
the-example-/-and-proof
を引数として渡せます。
connect()
の2番目のパラメーターは、
デフォルトのルートパラメーターを構成する任意のパラメーターを定義できます。
$routes->connect(
'/government',
['controller' => 'Pages', 'action' => 'display', 5]
);
この例では、 connect()
の2番目のパラメーターを使用してデフォルトパラメーターを定義しています。
もし、いろいろなカテゴリーの製品を顧客に対して提供するアプリケーションを作るのであれば、
ルーティングすることを考えるべきです。上記は、 /pages/display/5
ではなく /government
にリンクすることができます。
ルーティングの一般的な用途は、コントローラーとそのアクションの名前を変更することです。
/users/some_action/5
で users コントローラーにアクセスするのではなく、
/cooks/some_action/5
を使ってアクセスすることができます。
次のルートでそれが処理できます。
$routes->connect(
'/cooks/:action/*', ['controller' => 'Users']
);
これは Router に /cooks/
で始まるすべての URL は UsersController
に送るように
伝えています。 アクションは :action
パラメーターの値によって呼ばれるかどうか決まります。
ルート要素 を使って、ユーザーの入力や変数を受け付けるいろいろなルーティングが
できます。上記のルーティングの方法は、貧欲なスター (greedy star) を使います。
貧欲なスターは Router
がすべての位置指定引数を受け取ることを意味します。
それらの引数は 渡された引数 配列で有効化されます。
URL を生成するときにもルーティングは使われます。もし最初に一致するものがあった場合、
['controller' => 'users', 'action' => 'some_action', 5]
を使って
/cooks/some_action/5
と出力します。
これまでに接続したルートは、任意の HTTP 動詞と一致します。REST API を構築している際、
HTTP アクションを異なるコントローラーメソッドにマップすることがよくあります。
RouteBuilder
はヘルパーメソッドを提供し、特定の HTTP 動詞のルートをより簡単に定義します。
// GET リクエストへのみ応答するルートの作成
$routes->get(
'/cooks/:id',
['controller' => 'Users', 'action' => 'view'],
'users:view'
);
// PUT リクエストへのみ応答するルートの作成
$routes->put(
'/cooks/:id',
['controller' => 'Users', 'action' => 'update'],
'users:update'
);
上記のルートは、使用される HTTP 動詞に基づいて、同じ URL を異なるコントローラーアクションに マップします。GET リクエストは 'view' アクションに行き、PUT リクエストは 'update' アクションに 行きます。次の HTTP ヘルパーメソッドがあります。
GET
POST
PUT
PATCH
DELETE
OPTIONS
HEAD
これらのメソッドはすべてルートインスタンスを返すので、 流暢なセッター を活用してルートをさらに設定することができます。
バージョン 3.5.0 で追加: HTTP 動詞ヘルパーメソッドは追加されました。
あなたは独自のルート要素を指定し、コントローラーのアクションのパラメーターを
URL のどこに配置すべきなのかを定義することができます。リクエストされたとき、
これらのルート要素の値は、コントローラーの $this->request->getParam()
から取得できます。
カスタムルート要素を定義した場合、正規表現をオプションで指定できます。
これは CakePHP にどんな URL が正しいフォーマットなのかを伝えます。
正規表現を使用しなかった場合、 /
以外の文字はパラメーターの一部として扱われます。
$routes->connect(
'/:controller/:id',
['action' => 'view']
)->setPatterns(['id' => '[0-9]+']);
// 3.5 より前はオプション配列を使用
$routes->connect(
'/:controller/:id',
['action' => 'view'],
['id' => '[0-9]+']
);
上記の例は、 /コントローラー名/:id
のような形の URL で、任意のコントローラーの
モデルを表示するための、素早く作成する方法を示しています。 connect()
に渡した URL は
:controller
と :id
という2つのルート要素を指定します。この :controller
要素は
CakePHP のデフォルトルート要素であるため、ルーターが URL のコントローラー名をどのように照合し識別するかを
知っています。 :id
要素はカスタムルート要素で、 connect()
の3番目のパラメーターに
一致する正規表現を指定することで、より明確にする必要があります。
CakePHP は小文字とダッシュによって表された URL を :controller
を使った時には出力しません。
これを出力したい場合、上記の例を次のように書きなおしてください。
use Cake\Routing\Route\DashedRoute;
// 異なるルートクラスを持つビルダーを作成します。
$routes->scope('/', function ($routes) {
$routes->setRouteClass(DashedRoute::class);
$routes->connect('/:controller/:id', ['action' => 'view'])
->setPatterns(['id' => '[0-9]+']);
// 3.5 より前はオプション配列を使用
$routes->connect(
'/:controller/:id',
['action' => 'view'],
['id' => '[0-9]+']
);
});
DashedRoute
クラス :controller
を確認し、
:plugin
パラメーターを正しく小文字とダッシュによって表します。
CakePHP 2.x アプリケーションから移行するときに、小文字とアンダースコアーによる
URL が必要であるなら、 InflectedRoute
クラスを代わりに使用できます。
注釈
ルート要素で使用する正規表現パターンはキャプチャーグループを含んではいけません。 もし含んでいると、Router は正しく機能しません。
一度、ルートが定義されたら、 /apples/5
を呼ぶと
ApplesController の view()
メソッドを呼びます。 view()
メソッドの中で、
$this->request->getParam('id')
で渡された ID にアクセスする必要があります。
アプリケーションの中に一つのコントローラーがあり、URL にコントローラー名を表示されないようにするには、
全ての URL をコントローラーのアクションにマップすることができます。
たとえば、 home
コントローラーのアクションにすべての URL をマップするために、
/home/demo
の代わりに /demo
という URL を持つとすると、次のようにできます。
$routes->connect('/:action', ['controller' => 'Home']);
もし、大文字小文字を区別しない URL を提供したい場合、正規表現インライン修飾子を使います。
// 3.5 より前は setPatterns() の代わりにオプション配列を使用
$routes->connect(
'/:userShortcut',
['controller' => 'Teachers', 'action' => 'profile', 1],
)->setPatterns(['userShortcut' => '(?i:principal)']);
もう一つ例を挙げます。これであなたはルーティングのプロです。
// 3.5 より前は setPatterns() の代わりにオプション配列を使用
$routes->connect(
'/:controller/:year/:month/:day',
['action' => 'index']
)->setPatterns([
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
'day' => '0[1-9]|[12][0-9]|3[01]'
]);
これは、いっそう複雑になりますが、ルーティングがとても強力になったことを示しています。 この URL は4つのルート要素を持っています。1番目は、なじみがあります。デフォルトのルート要素で CakePHP にコントローラー名が必要なことを伝えています。
次に、デフォルト値を指定します。コントローラーにかかわらず index()
アクションを呼び出す必要があります。
最後に、数字形式の年と月と日に一致する正規表現を指定しています。正規表現の中で、丸括弧(グループ化)は サポートされていないことに注意してください。上記のように、代わりのものを指定できますが、 丸括弧によるグループ化はできません。
一度定義されると、このルートは /articles/2007/02/01
, /articles/2004/11/16
にマッチし、 $this->request->getParam()
の中の日付パラメーターを伴って
それぞれのコントローラーの index()
アクションにリクエストを渡します。
3.6.0 から、 :var
の代わりに {var}
をルート要素に使うことができます。
この新しいパラメータースタイルを使用すると、ルート要素を区切りのない区画に
埋め込むことができます。例:
$routes->connect(
'/images/resize/{id}/{width}x{height}',
['controller' => 'Images', 'action' => 'view']
);
上記は :var
スタイルのプレースホルダーを使って定義することは不可能です。
CakePHP には、いくつかの特別な意味を持つルート要素があります。 そして、特別な意味を持たせたくないなら、使わないでください。
controller
ルートのためのコントローラー名に使います。
action
ルートのためのコントローラーアクション名に使います。
plugin
コントローラーが配置されているプラグイン名に使います。
prefix
プレフィックスルーティング のために使います。
_ext
ファイル拡張子ルーティング のために使います。
_base
生成された URL からベースパスを削除するには false
をセットしてください。
アプリケーションがルートディレクトリーにない場合、 'cake relative' な URL の生成に使えます。
_scheme
webcal や ftp のように異なるスキーマのリンクを作成するために設定します。
現在のスキーマがデフォルトに設定されています。
_host
リンクで使用するホストを設定します。デフォルトは、現在のホストです。
_port
非標準のポートにリンクを作成するときにポートを設定します。
_full
true
にすると FULL_BASE_URL 定数が
生成された URL の前に加えられます。
#
URL のハッシュフラグメントを設定できます。
_ssl
true
にすると生成された URL を https に変換します。
false
にすると、強制的に http になります。
_method
HTTP 動詞/メソッドを使うために定義します。
RESTful なルーティング と一緒に使うときに役に立ちます。
_name
ルートの名前。名前付きルートをセットアップするときに、
それを指定するためのキーとして使えます。
各ルートに設定できる多くのルートオプションがあります。ルートを接続したら、
その流れるようなビルダーメソッドを使用してルートをさらに設定できます。
これらのメソッドは、 connect()
の $options
パラメーターの多くのキーを置き換えます。
$routes->connect(
'/:lang/articles/:slug',
['controller' => 'Articles', 'action' => 'view']
)
// GET と POST リクエストを許可
->setMethods(['GET', 'POST'])
// blog サブドメインにのみ一致
->setHost('blog.example.com')
// 渡された引数に変換されるルート要素を設定
->setPass(['slug'])
// ルート要素の一致するパターンを設定
->setPatterns([
'slug' => '[a-z0-9-_]+',
'lang' => 'en|fr|es',
])
// JSON ファイル拡張子も許可
->setExtensions(['json'])
// lang を永続的なパラメーターに設定
->setPersist(['lang']);
バージョン 3.5.0 で追加: 流れるようなビルダーメソッドは 3.5.0 で追加されました。
ルート要素 を使ってルートを接続している時に、ルート要素で
引数を渡したい時があると思います。 pass
オプションはルート要素が
コントローラーの関数に引数を渡せるようにするためのホワイトリストです。
// src/Controller/BlogsController.php
public function view($articleId = null, $slug = null)
{
// いくつかのコードがここに...
}
// routes.php
Router::scope('/', function ($routes) {
$routes->connect(
'/blog/:id-:slug', // 例えば /blog/3-CakePHP_Rocks
['controller' => 'Blogs', 'action' => 'view']
)
// 関数に引数を渡すためのルーティングテンプレートの中で、ルート要素を定義します。
// テンプレートの中で、ルート要素を定義します。
// ":id" をアクション内の $articleId にマップします。
->setPass(['id', 'slug'])
// `id` が一致するパターンを定義します。
->setPatterns([
'id' => '[0-9]+',
]);
});
今、リバースルーティング機能のおかげで、下記のように URL 配列を渡し、 CakePHP はルートに定義された URL をどのように整えるのかを知ることができます。
// view.ctp
// これは /blog/3-CakePHP_Rocks へのリンクを返します
echo $this->Html->link('CakePHP Rocks', [
'controller' => 'Blog',
'action' => 'view',
'id' => 3,
'slug' => 'CakePHP_Rocks'
]);
// 数字のインデックスを持つパラメーターを使えます。
echo $this->Html->link('CakePHP Rocks', [
'controller' => 'Blog',
'action' => 'view',
3,
'CakePHP_Rocks'
]);
時々、ルートのためにすべての URL パラメーターを記述することがとても煩雑で、
名前付きルートでパフォーマンスを上げたいと思うようになるでしょう。
ルートを接続するときに、 _name
オプションを指定できます。このプションは、
あなたが使いたいルートを識別するために、リバースルーティングで使われます。
// 名前付きでルートを接続
$routes->connect(
'/login',
['controller' => 'Users', 'action' => 'login'],
['_name' => 'login']
);
// HTTP メソッド指定でルートを命名 (3.5.0 以降)
$routes->post(
'/logout',
['controller' => 'Users', 'action' => 'logout'],
'logout'
);
// 名前付きルートで URL の生成
$url = Router::url(['_name' => 'logout']);
// クエリー文字列引数付きの
// 名前付きルートで URL の生成
$url = Router::url(['_name' => 'login', 'username' => 'jimmy']);
あなたのルートテンプレートに :controller
のようなルート要素が含まれている場合、
Router::url()
にオプションの一部としてそれらを提供したい場合があると思います。
注釈
ルート名はアプリケーション全体で一意でなければなりません。
違うルーティングスコープであっても、同じ _name
を二度使えません。
名前付きルートを構築する時、ルート名にいくつかの命名規則を適用したいでしょう。 CakePHP は、各スコープで名前のプレフィックスを定義することで、 より簡単にルート名を構築できます。
Router::scope('/api', ['_namePrefix' => 'api:'], function ($routes) {
// このルートの名前は `api:ping` になります。
$routes->get('/ping', ['controller' => 'Pings'], 'ping');
});
// ping ルートのための URL を生成
Router::url(['_name' => 'api:ping']);
// plugin() で namePrefix を使用
Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function ($routes) {
// ルートを接続。
});
// または、 prefix() で
Router::prefix('Admin', ['_namePrefix' => 'admin:'], function ($routes) {
// ルートを接続。
});
_namePrefix
オプションはネストしたスコープの中でも使えます。
それは、あなたの期待通りに動きます。
Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function ($routes) {
$routes->scope('/api', ['_namePrefix' => 'api:'], function ($routes) {
// このルートの名前は `contacts:api:ping` になります。
$routes->get('/ping', ['controller' => 'Pings'], 'ping');
});
});
// ping ルートのための URL を生成
Router::url(['_name' => 'contacts:api:ping']);
名前付きスコープに接続されているルートは命名されていているルートのみ追加されます。
名前なしルートはそれらに適用される _namePrefix
がありません。
バージョン 3.1 で追加: _namePrefix
オプションは 3.1 で追加されました。
多くのアプリケーションは特権を持ったユーザーが変更を加えるための管理者領域が必要です。
これはしばしば、特別な /admin/users/edit/5
のような URL を通してなされます。
CakePHP では、プレフィックスルーティングは, prefix
スコープメソッドによって
有効化されます。
use Cake\Routing\Route\DashedRoute;
Router::prefix('admin', function ($routes) {
// この全てのルートは `/admin` によってプレフィックスされます。
// そのために、 prefix => admin をルート要素として追加します。
$routes->fallbacks(DashedRoute::class);
});
プレフィックスは Controller
名前空間に属するようにマップされます。コントローラーと
分離してプレフィックスすることによって、小さくて単純なコントローラーをもつことができます。
プレフィックス付き及び付かないコントローラーに共通の動作は、継承や
コンポーネント やトレイトを使用してカプセル化できます。
このユーザーの例を使うと、 /admin/users/edit/5
にアクセスしたとき、
src/Controller/Admin/UsersController.php の edit()
メソッドを
5 を1番目のパラメーターとして渡しながら呼びます。
ビューファイルは、 src/Template/Admin/Users/edit.ctp が使われます。
/admin へのアクセスを pages コントローラーの index()
アクションに
以下のルートを使ってマップします。
Router::prefix('admin', function ($routes) {
// admin スコープの中なので、/admin プレフィックスや、
// admin ルート要素を含める必要はありません。
$routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
});
プレフィックスルートを作成するときに、 $options
引数で、追加のルートのパラメーターを
設定できます。
Router::prefix('admin', ['param' => 'value'], function ($routes) {
// ここで接続されているルートは '/admin' でプレフィックスされており、
// 'param' ルーティングキーを持っています。
$routes->connect('/:controller');
});
このようにプラグインスコープの中で、プレフィックスを定義できます。
Router::plugin('DebugKit', function ($routes) {
$routes->prefix('admin', function ($routes) {
$routes->connect('/:controller');
});
});
上記は /debug_kit/admin/:controller
のようなルートテンプレートを作ります。
接続されたルートは、 plugin
と prefix
というルート要素を持ちます。
プレフィックスを定義したときに、必要ならば複数のプレフィックスをネストできます。
Router::prefix('manager', function ($routes) {
$routes->prefix('admin', function ($routes) {
$routes->connect('/:controller');
});
});
上記のコードは、 /manager/admin/:controller
のようなルートテンプレートを生成します。
接続されたルートは prefix
というルート要素を manager/admin
に設定します。
現在のプレフィックスはコントローラーのメソッドから $this->request->getParam('prefix')
を通して利用可能です。
プレフィックスルーティングを使っているときは、prefix オプションを設定することが重要です。 以下は、リンクを HTML ヘルパーで作る方法です。
// プレフィックスルーティングする
echo $this->Html->link(
'Manage articles',
['prefix' => 'manager', 'controller' => 'Articles', 'action' => 'add']
);
// プレフィックスルーティングをやめる
echo $this->Html->link(
'View Post',
['prefix' => false, 'controller' => 'Articles', 'action' => 'view', 5]
);
注釈
フォールバックルートを接続する 前 にプレフィックスルートを接続してください。
プラグイン のためのルートは plugin()
メソッドを使って作成してください。
このメソッドは、プラグインのルートのための新しいルーティングスコープを作成します。
Router::plugin('DebugKit', function ($routes) {
// ここに接続されるルートは '/debug_kit' というプレフィックスが付き、
// このプラグインのルート要素には 'DebugKit' がセットされています。
$routes->connect('/:controller');
});
プラグインスコープを作るときに、 path
オプションでパス要素をカスタマイズできます。
Router::plugin('DebugKit', ['path' => '/debugger'], function ($routes) {
// ここに接続されるルートは '/debugger' というプレフィックスが付き、
// このプラグインのルート要素には 'DebugKit' がセットされています。
$routes->connect('/:controller');
});
スコープを使うときに、プレフィックススコープ内でプラグインスコープをネストできます。
Router::prefix('admin', function ($routes) {
$routes->plugin('DebugKit', function ($routes) {
$routes->connect('/:controller');
});
});
上記は、 /admin/debug_kit/:controller
のようなルートを作成します。
これは prefix
と plugin
のルート要素の組み合わせになります。
プラグインルートの構築について、詳しくは プラグインのルート にあります。
上記は、 /admin/debug_kit/:controller
のようなルーティングを作ります。
これは、 prefix
と plugin
をルート要素として持ちます。
URL 配列に plugin キーを追加することによって、プラグインを指すリンクを作成できます。
echo $this->Html->link(
'New todo',
['plugin' => 'Todo', 'controller' => 'TodoItems', 'action' => 'create']
);
逆に、現在のリクエストがプラグインに対してのリクエストであり、 プラグインではないリンクを作成する場合、次のようにできます。
echo $this->Html->link(
'New todo',
['plugin' => null, 'controller' => 'Users', 'action' => 'profile']
);
plugin => null
を設定することで、プラグインの一部ではないリンクを作成したいことを
Router に伝えられます。
良い検索エンジンのランキングを得るために、URL の中でダッシュを使うのを好む開発者もいるでしょう。
DashedRoute
クラスは、アプリケーションの中で、プラグイン、コントローラー、および
キャメルケースで書かれたアクション名をダッシュ記法の URL にルーティングすることができます。
例えば、 TodoItems
コントローラーの showItems()
アクションを持つ
ToDo
プラグインを使っていたとして、 /to-do/todo-items/show-items
でアクセスできるように、以下のルーター接続で可能になります。
Router::plugin('ToDo', ['path' => 'to-do'], function ($routes) {
$routes->fallbacks('DashedRoute');
});
ルートは、HTTP 動詞へルパーを使用して指定した HTTP メソッドとマッチできます。
Router::scope('/', function($routes) {
// このルートは POST リクエスト上でのみマッチします。
$routes->post(
'/reviews/start',
['controller' => 'Reviews', 'action' => 'start']
);
// 複数 HTTP メソッドとマッチします
// 3.5 より前は $options['_method'] をメソッドにセットして使用
$routes->connect(
'/reviews/start',
[
'controller' => 'Reviews',
'action' => 'start',
]
)->setMethods(['POST', 'PUT']);
});
配列を使うことで複数の HTTP メソッドとマッチできます。 _method
パラメーターは
ルーティングキーなので、 URL の解析と URL の生成の両方に使われます。
メソッド固有のルートの URL を生成するには、URL を生成する際に
_method
キーを含める必要があります。
$url = Router::url([
'controller' => 'Reviews',
'action' => 'start',
'_method' => 'POST',
]);
ルートは、指定のホストのみとマッチするように _host
オプションを使用できます。
任意のサブドメインとマッチするために *.
ワイルドカードを使用できます。
Router::scope('/', function($routes) {
// このルートは http://images.example.com のみマッチします。
// 3.5 より前は _host オプションを使用
$routes->connect(
'/images/default-logo.png',
['controller' => 'Images', 'action' => 'default']
)->setHost('images.example.com');
// このルートは http://*.example.com のみマッチします。
$routes->connect(
'/images/old-log.png',
['controller' => 'Images', 'action' => 'oldLogo']
)->setHost('*.example.com');
});
_host
オプションは URL 生成でも使用されます。 _host
オプションで正確なドメインを
指定する場合、そのドメインは生成された URL に含まれます。しかし、もしワイルドカードを
使用する場合、URL の生成時に _host
パラメーターを指定する必要があります。
// このルートを持つ場合、
$routes->connect(
'/images/old-log.png',
['controller' => 'Images', 'action' => 'oldLogo']
)->setHost('images.example.com');
// url を生成するために指定が必要です。
echo Router::url([
'controller' => 'Images',
'action' => 'oldLogo',
'_host' => 'images.example.com',
]);
バージョン 3.4.0 で追加: _host
オプションは 3.4.0 で追加されました。
異なるファイルの拡張子をルートで処理するために、スコープレベルだけでなくグローバルでも
拡張子を定義できます。グローバルな拡張子を定義するには、スタティックな
Router::extensions()
メソッドを介して保存できます。
Router::extensions(['json', 'xml']);
// ...
これは、スコープに関係なく、 以後に 接続された 全て のルートに影響します。
拡張子を特定のスコープに制限するために、 Cake\Routing\RouteBuilder::setExtensions()
メソッドを使用して定義することができます。
Router::scope('/', function ($routes) {
// 3.5.0 より前は `extensions()` を使用
$routes->setExtensions(['json', 'xml']);
});
これは、 setExtensions()
が呼ばれた 後の スコープの中で接続されている
全てのルートのために名前付き拡張子を有効にします。それは、ネストされたスコープの中で
接続されているルートも含まれます。グローバルの Router::extensions()
メソッドと
同様に、呼び出し前に接続されたルートは、拡張子を継承しません。
注釈
拡張子がセットされた 後 でのみ拡張子がルーティングに適用されるので、 拡張子を設定することはスコープの中で一番最初にやるべきことです。
また、再度開かれたスコープは、前回開いたスコープで定義した拡張子を 継承しない ことにも 注意してください。
拡張子を使うことで、一致したファイルの拡張子を除去し、残りをパースするように 伝えられます。もし /page/title-of-page.html のような URL を生成したいなら、 以下を使ってルートを設定します。
Router::scope('/page', function ($routes) {
// 3.5.0 より前は `extensions()` を使用
$routes->setExtensions(['json', 'xml', 'html']);
$routes->connect(
'/:title',
['controller' => 'Pages', 'action' => 'view']
)->setPass(['title']);
});
そして、ルートに対応するリンクを作成するために、次のようにします。
$this->Html->link(
'Link title',
['controller' => 'Pages', 'action' => 'view', 'title' => 'super-article', '_ext' => 'html']
);
拡張子が リクエストハンドリング で使われ、それによって コンテンツタイプに合わせた自動的なビューの切り替えを行います。
ミドルウェアをアプリケーション全体に適用することができますが、特定のルーティングスコープに ミドルウェアを適用すると、ミドルウェアが必要な場所にのみ適用できるため、適用の方法や範囲の 配慮がいらないミドルウェアにすることができます。
注釈
適用されるスコープ付きミドルウェアは RoutingMiddleware によって実行され、通常、アプリケーションのミドルウェアキューの最後に配置されます。
ミドルウェアをスコープに適用する前に、ルートコレクションに登録する必要があります。
// config/routes.php の中で
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Cake\Http\Middleware\EncryptedCookieMiddleware;
Router::scope('/', function ($routes) {
$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
$routes->registerMiddleware('cookies', new EncryptedCookiesMiddleware());
});
一度登録されると、スコープ付きミドルウェアは特定のスコープに適用されます。
$routes->scope('/cms', function ($routes) {
// CSRF & cookies ミドルウェアを有効化
$routes->applyMiddleware('csrf', 'cookies');
$routes->get('/articles/:action/*', ['controller' => 'Articles'])
});
ネストされたスコープがある状況では、内部スコープは、 スコープ内に適用されたミドルウェアを継承します。
$routes->scope('/api', function ($routes) {
$routes->applyMiddleware('ratelimit', 'auth.api');
$routes->scope('/v1', function ($routes) {
$routes->applyMiddleware('v1compat');
// ここにルートを定義。
});
});
上記の例では、 /v1
で定義されたルートは 'ratelimit'、 'auth.api'、および 'v1compat'
ミドルウェアが適用されます。スコープを再度開くと、各スコープ内のルートに適用されたミドルウェアが
分離されます。
$routes->scope('/blog', function ($routes) {
$routes->applyMiddleware('auth');
// ここに blog の認証が必要なアクションを接続
});
$routes->scope('/blog', function ($routes) {
// ここに blog の公開アクションを接続
});
上記の例では、 /blog
スコープの2つの用途はミドルウェアを共有しません。
ただし、これらのスコープは両方とも、そのスコープ内で定義されたミドルウェアを継承します。
ルートコードを DRY に保つ助けになるよう、 ミドルウェアをグループにまとめることができます。一度まとめられたグループは、 ミドルウェアのように適用することができます。
$routes->registerMiddleware('cookie', new EncryptedCookieMiddleware());
$routes->registerMiddleware('auth', new AuthenticationMiddleware());
$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
$routes->middlewareGroup('web', ['cookie', 'auth', 'csrf']);
// グループの適用
$routes->applyMiddleware('web');
バージョン 3.5.0 で追加: スコープ付きミドルウェアとミドルウェアグループは 3.5.0 で追加されました。
Router はコントローラーへの RESTful なルートを簡単に生成します。 RESTful なルートはアプリケーションの API エンドポイントを作るときに有効です。 recipe コントローラーに REST アクセスできるようにしたい場合、このようにします。
// config/routes.php 内で...
Router::scope('/', function ($routes) {
// 3.5.0 より前は `extensions()` を使用
$routes->setExtensions(['json']);
$routes->resources('Recipes');
});
最初の行は、簡単に REST アクセス可能にするために、いくつかのデフォルトルートをセットしています。 アクセス対象のメソッドには、最終的に受け取りたいフォーマット (例えば xml, json, rss) の指定が 必要です。これらのルートは、HTTP リクエストメソッドに対応しています。
HTTP format |
URL.format |
対応するコントローラーアクション |
---|---|---|
GET |
/recipes.format |
RecipesController::index() |
GET |
/recipes/123.format |
RecipesController::view(123) |
POST |
/recipes.format |
RecipesController::add() |
PUT |
/recipes/123.format |
RecipesController::edit(123) |
PATCH |
/recipes/123.format |
RecipesController::edit(123) |
DELETE |
/recipes/123.format |
RecipesController::delete(123) |
使用されている HTTP メソッドは、いくつかの異なるソースから検出されます。 優先順位の順のソースは次のとおりです。
_method
POST 変数
X_HTTP_METHOD_OVERRIDE
ヘッダー
REQUEST_METHOD
ヘッダー
_method
POST 変数の値を使う方法は、ブラウザーを使った REST クライアントの場合
(または POST でできる何か)に便利です。エミュレートしたい HTTP リクエストの名前を
_method
の値にセットするだけです。
スコープの中で一度リソースに接続すると、サブリソース (リソースの下層) にもルートを接続できます。 サブリソースのルートは、オリジナルのリソース名と id パラメーターの後に追加されます。例えば:
Router::scope('/api', function ($routes) {
$routes->resources('Articles', function ($routes) {
$routes->resources('Comments');
});
});
これで articles
と comments
両方のリソースルートを生成します。
この comments のルートは次のようになります。
/api/articles/:article_id/comments
/api/articles/:article_id/comments/:id
CommentsController
の article_id
を次のように取得できます。
$this->request->getParam('article_id');
デフォルトでは、リソースルートは、スコープに含まれる同じプレフィックスにマップします。 もし、ネストしたリソースのコントローラーとそうでないリソースのコントローラー両方を持つ場合、 プレフィックスを利用して各コンテキスト内で異なるコントローラーを使用できます。
Router::scope('/api', function ($routes) {
$routes->resources('Articles', function ($routes) {
$routes->resources('Comments', ['prefix' => 'articles']);
});
});
上記は、「Comments」リソースを App\Controller\Articles\CommentsController
に
マップします。コントローラーを分けることで、あなたのコントローラーのロジックをシンプルに保つことが
できます。このやり方で作成されたプレフィックスは、 プレフィックスルーティング と互換性があります。
注釈
あなたが望む深さまでリソースをネストできますが、 2段階以上の深さにネストさせることはお勧めしません。
バージョン 3.3 で追加: 3.3 で resources()
に prefix
オプションが追加されました。
デフォルトでは CakePHP は、各リソースに対して6つのルートを接続します。
特定のリソースに対して、特定のルートのみを接続させたい場合、 only
オプションを使います。
$routes->resources('Articles', [
'only' => ['index', 'view']
]);
これで読み込み専用のリソースルートが作られます。このルート名は create
,
update
, view
, index
, と delete
です。
ルートを接続するときに使われるコントローラーのアクション名を変更したい場合があるでしょう。
例えば、 edit()
アクションを put()
で呼びたいときに、
actions
キーをアクション名のリネームに使います。
$routes->resources('Articles', [
'actions' => ['update' => 'put', 'create' => 'add']
]);
上記は put()
を edit()
アクションの代わりに使い、 add()
を create()
の代わりに使います。
map
オプションを使用して、追加のリソースメソッドをマップできます。
$routes->resources('Articles', [
'map' => [
'deleteAll' => [
'action' => 'deleteAll',
'method' => 'DELETE'
]
]
]);
// これは /articles/deleteAll へ接続します。
デフォルトルートに加えて、これは /articles/delete_all へのルートに接続します。 デフォルトでは、パスセグメントはキー名に一致します。'path' キーを、パスをカスタマイズするための リソースの定義の中で使えます。
$routes->resources('Articles', [
'map' => [
'updateAll' => [
'action' => 'updateAll',
'method' => 'DELETE',
'path' => '/update_many'
],
]
]);
// これは /articles/update_many に接続します。
'only' と 'map' を定義した場合、マップされたメソッドが 'only' リストにもあるか確かめましょう。.
resources()
の $options
配列の connectOptions
キーで connect()
を使った設定ができます。
Router::scope('/', function ($routes) {
$routes->resources('Books', [
'connectOptions' => [
'routeClass' => 'ApiRoute',
]
];
});
デフォルトで、複数語のコントローラーの URL フラグメントは、コントローラー名のアンダースコアー形式です。
例えば、 BlogPosts
の URL フラグメントは、 /blog_posts になります。
inflect
オプションを使って別の変化形を指定できます。
Router::scope('/', function ($routes) {
$routes->resources('BlogPosts', [
'inflect' => 'dasherize' // ``Inflector::dasherize()`` を使用
]);
});
上記は、 /blog-posts/* スタイルの URL を生成します。
注釈
CakePHP 3.1 から、公式の app スケルトンは、 DashedRoute
をデフォルトルートクラス
として使用します。 URL の一貫性を保つために、リソースルートを接続する際に
'inflect' => 'dasherize'
オプションを使用することを推奨します。
デフォルトでは、リソースルートは、URL セグメントのリソース名の語形変化された形式を使用します。
path
オプションでカスタム URL セグメントを設定することができます。
Router::scope('/', function ($routes) {
$routes->resources('BlogPosts', ['path' => 'posts']);
});
バージョン 3.5.0 で追加: path
オプションは 3.5.0 で追加されました。
渡された引数は、リクエストされた際に使用される追加の引数、もしくはパスセグメントです。 これらはしばしば、コントローラーメソッドにパラメーターを渡すために使われます。
http://localhost/calendars/view/recent/mark
上記の例では、 recent
と mark
の両方が CalendarsController::view()
に引数として渡されます。渡された引数は3つの方法でコントローラーに渡されます。
1番目は、引数としてアクションを呼ばれたときに渡し、2番目は、
$this->request->getParam('pass')
で数字をインデックスとする配列で呼べるようになります。
カスタムルートを使用するときに、渡された引数を呼ぶために特定のパラメーターを強制することができます。
前述の URL にアクセスして、次のようなコントローラーアクションがあるとすると、
class CalendarsController extends AppController
{
public function view($arg1, $arg2)
{
debug(func_get_args());
}
}
次の出力を得ます。
Array
(
[0] => recent
[1] => mark
)
コントローラーとビューとヘルパーの $this->request->getParam('pass')
でも、
これと同じデータが利用可能です。pass 配列中の値は、
呼ばれた URL に現れる順番をもとにした数字のインデックスになります。
debug($this->request->getParam('pass'));
上記の出力は以下になります。
Array
(
[0] => recent
[1] => mark
)
ルーティング配列 を使って URL を生成するとき、配列に文字列キーなしの値として 引数を加えます。
['controller' => 'Articles', 'action' => 'view', 5]
5
は引数として渡されるときには数字キーを持ちます。
URL の生成やリバースルーティングは、すべてのコードの変更なしに URL の構造を簡単に変更する CakePHP の機能です。URL を定義するために ルーティング配列 を使用することで、 あとで変更を加えても、生成された URL は自動的に更新されます。
次のように URL を文字列で作成し、
$this->Html->link('View', '/articles/view/' . $id);
そして、あとで /articles
は本当は 'posts' と呼ぶべきであると判断した場合、
アプリケーション全体で URL を変更する必要があります。一方、次のように link を定義し、
$this->Html->link(
'View',
['controller' => 'Articles', 'action' => 'view', $id]
);
そして、URL を変更すると判断した場合、ルートを定義することで変更できます。 これは、受け取る URL のマッピングと生成される URL の両方を変更します。
URL 配列を使うとき、特別なキーを使用して、文字列パラメーターによるクエリーと ドキュメントフラグメントを定義できます。
Router::url([
'controller' => 'Articles',
'action' => 'index',
'?' => ['page' => 1],
'#' => 'top'
]);
// このような URL が生成されます
/articles/index?page=1#top
Router はルーティング配列の中の未知のパラメーターをクエリー文字列パラメーターに変換します。
?
は CakePHP の古いバージョンとの後方互換性のために提供します。
URL を生成するときに、特別なルート要素が使用できます。
_ext
ファイル拡張子のルーティング (拡張子)ルーティングに使います。
_base
生成された URL からベースパスを削除するには false
をセットしてください。
アプリケーションがルートディレクトリーにない場合、 'cake relative' な URL の生成に使います。
_scheme
webcal
や ftp
のように異なるスキーマのリンクを作成するために設定します。
現在のスキーマにデフォルト設定されています。
_host
リンクのためのホストを設定します。デフォルトは、現在のホストです。
_port
非標準なポートのリンクを作成するときにポートを設定します。
_method
URL が存在する HTTP メソッドを定義します。
_full
true
にすると、 FULL_BASE_URL
定数 が
生成された URL の前に加えられます。
_ssl
true
にすると普通の URL から https に変換します。
false
にすると、強制的に http になります。
_name
ルートの名前。名前付きルートをセットアップするとき、それを指定するためのキーとして使います。
リダイレクトルーティングは受け取るルートに対して HTTP ステータスの 30x リダイレクトを発行し、 異なる URL に転送することができます。これは、リソースが移動し、同じ内容の 2 つの URL を 公開したくないことをクライアントアプリケーションに通知する場合に便利です。
リダイレクトルートは通常のルートとは異なり、条件に一致した場合、 実際にヘッダーリダイレクトを実行します。 リダイレクトは、アプリケーション内部や外部へ遷移します。
Router::scope('/', function ($routes) {
$routes->redirect(
'/home/*',
['controller' => 'Articles', 'action' => 'view'],
['persist' => true]
// もしくは $id を引数として受け取る view アクションの
// デフォルトルーティングは ['persist'=>['id']] のようにする
);
});
/home/*
から /articles/view
へのリダイレクトし /articles/view
にパラメーターを渡します。
リダイレクト先として配列を使うことで、URL 文字列を定義するために、他のルートを使用できます。
文字列 URL を遷移先として使用することで外部にリダイレクトできます。
Router::scope('/', function ($routes) {
$routes->redirect('/articles/*', 'https://google.com', ['status' => 302]);
});
これは、 /articles/*
から https://google.com
へ HTTP 302 ステータスのリダイレクトをします。
エンティティールーティングでは、エンティティー、配列またはオブジェクトを使用して、
ArrayAccess
をルーティングパラメーターのソースとして実装できます。これにより、
ルートをより簡単にリファクタリングし、少ないコードで URL を生成することができます。
たとえば、次のようなルートで開始するとします。
$routes->get(
'/view/:id',
['controller' => 'Articles', 'action' => 'view'],
'articles:view'
);
次のようにして、このルートへの URL を生成できます。
// $article は、ローカルスコープ内のエンティティーです。
Router::url(['_name' => 'articles:view', 'id' => $article->id]);
後で、SEO 目的のために URL に記事のスラッグを付加したくなることもあるでしょう。これを行うには、
articles:view
ルートへの URL を生成しているところを全て更新する必要があります。
これには時間がかかることがあります。エンティティールートを使用する場合、article エンティティー全体を
URL 生成に渡すことで、URL がより多くのパラメーターが必要となったとしても、
すべての更新をスキップできます。
use Cake\Routing\Route\EntityRoute;
// このスコープの rest のためのエンティティールートを作成します。
$routes->setRouteClass(EntityRoute::class);
// 以前と同じようにルートを作成します。
$routes->get(
'/view/:id',
['controller' => 'Articles', 'action' => 'view'],
'articles:view'
);
これで、 _entity
キーを使って URL を生成することができます。
Router::url(['_name' => 'articles:view', '_entity' => $article]);
これは、提供されたエンティティーから id
プロパティーと slug
プロパティーの両方を抽出します。
バージョン 3.6.0 で追加: エンティティールーティングは 3.6.0 で追加されました。
カスタムルートクラスは、個々のルートがリクエストをパースし、リバースルーティングを扱えるようにします。 Route クラスには、いくつかの規約があります。
ルートクラスは、アプリケーションやプラグイン内にある Routing\\Route
名前空間で
見つけられるはずです。
ルートクラス Cake\Routing\Route
を拡張します。
ルートクラスは match()
と parse()
の一方もしくは両方を使います。
parse()
メソッドは、受け取った URL をパースするために使用されます。
これは、コントローラーとアクションに分解されるリクエストパラメーターの配列を生成する必要があります。
このメソッドは、一致しなかった時に false
を返します。
match()
メソッドは URL パラメーターの配列に一致するか確かめるために使い、
URL を文字列で生成します。URL パラメーターがルートに一致しない時は、 false
を返します。
カスタムルートクラスを routeClass
オプションを使って設定することができます。
$routes->connect(
'/:slug',
['controller' => 'Articles', 'action' => 'view'],
['routeClass' => 'SlugRoute']
);
// また、スコープの中で routeClass を設定することもできます。
$routes->scope('/', function ($routes) {
// 3.5.0 以前では `routeClass()` を使用
$routes->setRouteClass('SlugRoute');
$routes->connect(
'/:slug',
['controller' => 'Articles', 'action' => 'view']
);
});
このルートは SlugRoute
のインスタンスを生成し、カスタムパラメーター処理を実装することができます。
標準的な プラグイン記法 を使ってプラグインルートクラスを使用できます。
デフォルト Route
以外のすべての他のルートクラスをデフォルトの基づくルートに
使いたいときには、 Router::defaultRouteClass()
を呼ぶことによって すべてのルートを
セットアップする前に、それぞれのルートのための特定の routeClass
オプションを持つことを
避けます。例えば、下記を使います。
use Cake\Routing\Route\InflectedRoute;
Router::defaultRouteClass(InflectedRoute::class);
この後に接続されたすべてのルートに InflectedRoute
ルートクラスが使用されます。
引数なしにこのメソッドを呼ぶと、現在のデフォルトルートクラスを返します。
fallbacks メソッドはデフォルトルートをショートカットする簡単な方法です。
このメソッドは、渡されたルーティングクラスによって定義されたルールを使用します。もし、
クラスが定義されていない場合、 Router::defaultRouteClass()
で返されたクラスが使用されます。
フォールバックを次のように呼びます。
use Cake\Routing\Route\DashedRoute;
$routes->fallbacks(DashedRoute::class);
次の明示的な呼び出しと同等です。
use Cake\Routing\Route\DashedRoute;
$routes->connect('/:controller', ['action' => 'index'], ['routeClass' => DashedRoute::class]);
$routes->connect('/:controller/:action/*', [], ['routeClass' => DashedRoute::class]);
注釈
フォールバックを使ったデフォルトルートクラス (Route
) もしくは、
:plugin
や :controller
ルート要素をもつ任意のルートを使用すると
URL の大文字小文字の区別がなくなります。
URL フィルター関数で URL の生成プロセスをホックできます。 フィルター関数は、 ルーティングに一致する 前 に呼ばれます。 これは、ルーティングする前に URL を用意します。
コールバックフィルター関数は以下のパラメーターを持ちます。
$params
生成されている URL パラメーター。
$request
現在のリクエスト
URL フィルター関数は 常に フィルターされていなくても、パラメーターを返します。
URL フィルターは永続的なパラメーターなどを簡単に扱う機能を提供します。
Router::addUrlFilter(function ($params, $request) {
if ($request->getParam('lang') && !isset($params['lang'])) {
$params['lang'] = $request->getParam('lang');
}
return $params;
});
フィルター関数は、それらが接続されている順番に適用されます。
別のユースケースでは、実行時に特定のルートを変更しています。 (プラグインルートの例)
Router::addUrlFilter(function ($params, $request) {
if (empty($params['plugin']) || $params['plugin'] !== 'MyPlugin' || empty($params['controller'])) {
return $params;
}
if ($params['controller'] === 'Languages' && $params['action'] === 'view') {
$params['controller'] = 'Locations';
$params['action'] = 'index';
$params['language'] = $params[0];
unset($params[0]);
}
return $params;
});
これは以下のルートを
Router::url(['plugin' => 'MyPlugin', 'controller' => 'Languages', 'action' => 'view', 'es']);
このように置き換えます。
Router::url(['plugin' => 'MyPlugin', 'controller' => 'Locations', 'action' => 'index', 'language' => 'es']);
警告
もし ルーティングミドルウェア のキャッシュ機能を利用しているのなら、
フィルターはキャッシュされたデータの一部ではないため、
アプリケーションの bootstrap()
でフィルター関数を定義しなければなりません。
CakePHP 3.0 から名前付きパラメーターが削除されたとしても、 アプリケーションは URL にそれを含んだ状態で公開されています。 名前付きパラメーターを含んだ URL の受け付けを継続できます。
コントローラーの beforeFilter()
メソッドで、 parseNamedParams()
呼ぶことで渡された引数のすべての名前付きパラメーターを展開できます。
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
Router::parseNamedParams($this->request);
}
これは、 $this->request->getParam('named')
にすべての渡された引数にある
名前付きパラメーターを移します。すべての名前付きパラメーターとして変換された引数は
渡された引数のリストから除去されます。