CakePHP携帯用ビューのRoute設定
携帯ビュー向けRoutingが一部アクションでうまく作動しない件について、解決。。
携帯向けビューのprefixをroute.phpで設定する場合、
URLで変数が渡されるケースがあるなら、そのパターンや変数名を明確に定義しなくてはならないようです。
このブログには書いてませんが*1、CakePHPによる携帯対応サイトの定法に乗っ取り、以下を参考に http://example.com/m/* にアクセスすると携帯ビューとなるように実装しています。
CakePHP 1.2で携帯用ビューを表示する - Shin x blog
http://www.multiburst.net/ElectricBrain/2009/02/cakephp-mobile-site
今までindex, view, add, delete, login, logout, listview*2などのアクションを実装して不具合がなかったのですが、
users情報のうち、パスワードだけを更新するアクションchange_passwordを実装したところ、$form->createで生成されるFROMタグのactionに、/m/が自動挿入されませんでした。*3
view記載 echo $form->create('User', array('action' => 'change_password')); ↓ 出力 <form id="UserChangePasswordForm" method="post" action="/rootDir/users/change_password/1">
addなどだと、自然に/m/が入ります。
<?php echo $form->create('User'); ?> ↓ <form id="UserAddForm" method="post" action="/rootDir/m/users/add">
cake/libs以下を、FormヘルパーからRouter.phpまで辿って調査の結果。
原因は、app/config/route.phpの指定不足でした。
prefix=mobileとなるRouteingのルールに、変数名=idのパラメータが含まれる場合を追加しなくてはなりませんでした。
修正前*4
if (preg_match("/^".str_replace("/", "\/", $this->webroot)."m\//", $_SERVER['REQUEST_URI'])) { Router::connect('/m/:controller/:action/*', array('prefix' => 'mobile')); }
修正後
if (preg_match("/^".str_replace("/", "\/", $this->webroot)."m\//", $_SERVER['REQUEST_URI'])) { Router::connect('/m/:controller/:action/*', array('prefix' => 'mobile')); Router::connect('/m/:controller/:action/:id', array('prefix' => 'mobile')); }
パラメータに$idが入ってきますよ、という情報がroute.phpの設定にないと、以下のチェックを通過できないのです。
function mapRouteElements($route, $url) { (中略) $paramsKeys = array_keys($params); $defaultsKeys = array_keys($defaults); if (!empty($params)) { if (array_diff($paramsKeys, $routeParams) != array()) { <=ここ。 return false; } (後略)
$paramsKeys = array('controller', 'action', 'id');
でしたが、修正前の状態では
$defaultsKeys = array('controller', 'action'); *6
array_diffを取ると、array("id")が残るのでreturn falseで捕まってしまう。
route.phpに /m/:controller/:action/:id のケースを明示することで、$defaultsKeysにidが追加されてパスできるようになりました。
今までhtmlヘルパーによるlink作成などで、なんとなく不具合なさそうに動いていたのは、
Router::connect('/m/:controller/:action/*', array('prefix' => 'mobile'));
でキャプチャしていたあたりと関係ありそうです・・・
参考URLでは
Router::connect('/m/:controller/:action', array('prefix' => 'mobile'));
とあるのですが、idがはいるURLが変換できないために
「ではアスタリスクいれてみよう。おお、うまく行った」
・・・・と対応したような気がします*7
アスタリスクで対応するのも、route.phpのサンプルケースをみるとありかと思いますが、
それではうまく行かない場合もある、というケースでした・・・・