久しぶりにcakeの記事を書きます。
最近、cakePHP以外のフレームワークにも浮気しようとしているのですが勇気がでません。
要件は悩み | チャゲってる日々 – @tyageにて書いてあります。
一応解決したのですが、先ほどの記事を今読むと、かなり意味不明な内容になっているため、簡単にまとめてみます。
やりたかったこと
タイトルにあるように、アクセスした際のURLにあるパラメータを保持する方法を探していました。
具体的には、
「/users/view/1」というURLにアクセスして表示される「/users/mail/1」というリンクが、
「/iframe/users/view/1」というURLでアクセスすると、「/iframe/users/mail/1」というリンクに変わるといいなーという話です。
リンクに限らず、formの送信先URL等や、controller側の操作($this->flashとか)でも適用されてほしいので、
自作Helperを作るだけでは対応しきれません。
Prefix Routing
cakePHPにはPrefix Routing機能があります。
その機能の説明は省きますが、その機能によりHTMLヘルパーを使用した際等に、URLに使用中のprefixをつけることができます。
例えば、adminというprefixを使用している時に、
// APP/views/pages/index.ctp, // APP/views/pages/admin_index.ctp <?= $html->link('hello', array('controller' => 'users', 'action' => 'add')) ?> |
という2つの内容の同じviewがあるとします。
その時、/pages/indexというURLでアクセスすると、リンク先は「/users/add」となりますが、
/admin/pages/indexというURLの場合、リンク先は「/admin/users/add」と、prefixのadminが維持される訳です。
しかしここで当たり前なのですが厄介なのが、先ほどの例でadminというprefixをつけた場合、
呼び出されるactionは「index」から「admin_index」となり、
呼び出されるviewも「index.ctp」から「admin_index.ctp」となるため、
prefixごとにactionとviewを作成する必要が出てきます。
なので、今回のように単純にURLにprefixを維持させたい場合にprefixを使うと、無駄な手間がかかることが分かります。
対策
今回の場合、prefix機能が働いてほしいのは、URLを整形する際です。
(URLを整形たびに、現在有効なprefixを調べて付加しているようです。)
逆に、呼び出すactionを呼び出すときにprefixが働いてしまうと、やっかいなことになります。
そこで、呼び出すactionが決定した後にprefixを再指定すればいいのでは、という結論に至りました。
とりあえずcakeのコードを調べた結果、以下のようにすれば望んでいたことができるようになりました。
// config/routes.php <?php ... Router::connect('/iframe/:controller', array('iframe' => true)); Router::connect('/iframe/:controller/:action/*', array('iframe' => true)); |
// controllers/app_controller.php <?php ... function beforeFilter() { if (!empty($this->params['iframe'])) { $this->layout = 'iframe'; Configure::write('Routing.prefixes', array('iframe')); $router =& Router::getInstance(); $router->__setPrefixes(); } } |
「config/routes.php」にてiframe prefixがあるかどうかをパラメータで指定し、
その後controller側で無理やり新しいprefixをRouterに叩き込んでいます。
これで、「インラインフレームでアクセスしたときだけレイアウトを変える」ということができます!
(※ただしそのアプリ内のURLに限る)
結論
やっぱり上手く説明できない