独自namedパラメータを使って逆ルーティング

結構な忙しさなのですが、id:cakephperさんのTweetをみて妙に納得してしまったので、昨日はまってた事をまとめました。

CakePHP 1.2.5で開発中です。

namedパラメータはなかなかに便利なのですが、独自のnamedパラメータを使っているURLの逆ルーティングではまったのでちょっと調べてみました。

通常の以下の様なルーティングであれば、独自のnamedパラメータも問題なく使えます。

<?php
Router::connect('/:controller/:action/*');

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 'mode' => 'test')) ;
// 正しく変換できます
// $url = "/posts/index/mode:test"

ところがprefix routingを使ったりすると状況が変わります。例えば、以下の様に携帯対応のためにprefix routingとURLにセッションキーを埋め込むような場合ですね。

<?php
Router::connect('/m/:session/:controller/:action/*', 
  array('prefix' => 'mobile', 'mobile' => true), 
  array('session' => '[a-zA-Z0-9]{32}')
);

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 
  'mobile' => true, 'page' => 1, 'session' => '11111111112222222222333333333344')) ;
// page等のCakePHPで標準的に使われているnamedパラメータは問題なし
// $url = "/m/11111111112222222222333333333344/posts/view/page:1"

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 
  'mobile' => true, 'mode' => 'test', 'session' => '11111111112222222222333333333344')) ;
// 独自のnamedパラメータを使うとこんな感じになってしまいます
// $url = "/posts/view/mobile:1/mode:test/session:11111111112222222222333333333344"

色々と調べた結果、namedパラメータとして使用する変数名を登録することができるようです。

Routerクラスに定義されている、connectNamedを使うことで使用可能なnamedパラメータをカスタマイズすることができます。
例えば上記の例の場合には、以下のように指定すると正常に変換できるようになります。

<?php
// 'default'=>true を指定しないとCakePHP標準のnamedパラメータを上書きしてしまうので注意!
Router::connectNamed(array('mode'), array('default'=>true)) ;

connectNamedメソッドのコメントを見ると適用するコントローラやアクションを指定出来そうなのですが、私が試した範囲では制限をかけられませんでした。(アプリすべてのコントローラに適用されます)
追いかけきれていないので、時間ができたらもう少し調べてみたいと思います。

参考

  • ルーティングの設定に失敗するとハマる事がおおいので、しっかりテストも書きましょう!ということで、ルーティングのテストについては以下の新原さんの記事がとても参考になります!