最初に前置きしますが、これは僕のプロジェクトの環境に由来することかもしれませんので、一般的なTIPSではないことをご了承ください。
【前提条件】
- とりあえず検証したのはWindows+xampp1.7.0+CakePHP1.2.6
- config/routes.phpにRouter::parseExtensions();を設定している(たしかRSS配信のためだったと思う)
- /genres/clip/100にアクセスした場合に、100という引数をclip処理して/genres/index/100にリダイレクトする
【問題点】
$this->redirect(“/genres/index/100”);でリダイレクトすると「/genres/index/pass~Array/url~Array」こんな感じでURLが壊れてしまい、引数なしの/genres/indexにアクセスしてしまう。
【原因】
redirectに指定したurl「”/genres/index/100″」は、app_controller.phpに追加した__redirect_url($url)の処理でRouter::parse($url)すると配列に置き換えられる。
この置き換えられた配列を、元のredirect処理(parent::redirect)の処理中のRouter::url($url)すると、pass:Arrayに変換してしまうのが原因のようだ。
ちなみにrouter.phpに記載しているRouter::parseExtensions();を追加すると$this->params[url]に配列でarray(“ext” => “html”)が追加されるし、引数のあるパスを渡せば$this->params[‘pass’]に配列で引数が追加される。
僕の環境だとRouter::url()に渡す配列にこれらが含まれている場合、返り値にurl:Arrayやpass:Arrayが含まれてしまうようだ。
これに関してはktai Libraryを組み込んでいない別プロジェクトでも同じだからCakePHPの仕様な気もするけど、後述する対処方法が見つかったので詳しく調べていない。
【解決方法】
コントローラでリダイレクトする際に渡す引数を配列で渡す。
$this->redirect(array("controller" => "genres", "action" => "index", 100));
$this->redirect(“/genres/index/100”);としていたところを、$this->redirect(array(“controller” => “genres”, “action” => “index”, 100));とすることで解決した。(この書き方をしなくてはならないのは面倒だけども。。。)
ktai Libraryの作者MASA-Pさんの著書「PHPで作る携帯サイト デベロッパーズガイド」のP88にCakePHPのredirect処理についての記述があるんだけど、サンプルソースには$this->redirect(Router::url(“action” => “add”));のように書いてあったり、「外部サイトを定義することはできない」*1 と書いてあるのだけど、普段は外部サイトへのリダイレクトでも使っていたし、redirect()の引数指定も今までこのような書き方を知らなかったのでとても悩んだ。
【最後に】
CakePHPの基本くらいは知っているつもりでデベロッパーズガイドのCakePHPについて書かれた章は飛ばしていたんですが、CakePHPについてもとても詳しく書いてあるし、中身も濃いのでもう一度勉強するつもりで最初から読み直してみようと思います。
ちなみにController::redirect(“/genres/index/100”);のようなurlをstring渡しでうまくいくという方がいらっしゃいましたら、「できるよー」と声をかけてもらえると嬉しいです(笑)できる事実があるなら何とか調べてみたいと思いますので^^)
【余談】
先日、debug値が0以外のときにセッションIDの持ち回りができない件もMASA-Pさんに質問させてもらったんだけど、テストサイトでは問題なく動いているとのことだったので、やっぱり僕のCakePHPの使い方に何か問題があるのかも知れないです。。
他の方と比べたことがないのでわからないけど、結構クセのある使い方をしているかもしれません。
上記がすべての方に当てはまるということはないと思いますので、あらかじめご了承くださいね。
- 実機で試していないのだけど携帯では外部サイトにリダイレクトできない。という意味なのかな? [↩]
コメント
リダイレクトに入れられる値は、いつからかstrでもarrayでも良くなったらしく、昔はarrayを入れられなかったのでRouter::url()で変換してから入れる方法があったので、そのなごりが(^^;。今はarrayを直接突っ込めるはずです。
また、外部サイトに関しても同様に突っ込んではいけないものだったのですが、今は大丈夫になっています。
逆にRouter::perse()はstrから逆ルーティングを行ってarray形式で入手できるものですが、この中にarrayを入れてはいけなくて、それで不具合が出てしまっています。また外部サイトについても同様です。
そんなわけで、Ktai Library 0.2.3でこの辺の流れををきっちり直しましたので、ダウンロードしてapp_controller.php.ktaiの該当箇所をコピっていただければしっかり動くと思います。
まだ不具合出るようでしたら是非教えてください。
丁寧に説明してくださり本当にありがとうございます!
そういう経緯があったのですね。
ただ記事中に書き忘れてしまったのですが03-20にリリースの0.2.3で試して記事の現象が起こりました。
router.phpにRouter::parseExtensions();のほかにも自前で設定したものもあるので、もしかしたらそれが影響しているのかもしれません。
時間が取れたら検証してご報告したいと思います。
コメントをいただきありがとうございましたm_ _m