てきとうなさいと べぇたばん

CakePHPめも error404とディレクトリ階層を1段階下げた時の対処

CakePHPでerror404をthemedでも使えるようにする

いまさら、1.3系の話しである。

そもそも、404 Not foundをどう処理しているのか

app_error.phpからerror404メソッドを作ってget_classをすると、AppError::$controllerにはCakeErrorControllerをいうクラスがある。

このファイルは、cake/libs/error.phpの中にある。__constructしか無い、結構シンプルなクラスである。

Componentを作成すればいい

CakeErrorControllerにある処理には、コンポーネントのinitializeメソッドがあるため、コンポーネント経由ならば通常ページと同じように処理できたので、そうした。

ディレクトリを1段階下げる場合でも使えるようにする

ディレクトリ階層を1段階下げた時のHtmlHelper::linkの挙動について

/mobileというディレクトリへ階層を1段階下げると、HtmlHelper::linkに配列での形式で渡すと、帰ってくるリンクがディレクトリ階層が1段階下がっている。たとえば、以下のような。

<?php echo $this->Html->link("link", array('controller' => 'hoge', 'action' => 'huga')); ?>

以下のようになる。ちと困った。

→<a href="/mobile/mobile/hoge/huga">link</a>

内部ではRouter::urlを使用している。その説明の中にそれっぽいヒントを見つけた。

base - Set to false to remove the base path from the generated url. If your application is not in the root directory, this can be used to generate urls that are 'cake relative'. cake relative urls are required when using requestAction.

この説明文によれば、引数の配列の要素にbaseというキーを追加してfalseを指定すると、cakeは相対URLを生成するらしい。

<?php echo $this->Html->link("link", array('base' => false, 'controller' => 'hoge', 'action' => 'huga')); ?>

確かに、以下のようになった。これで大丈夫だ。

→<a href="/hoge/huga">link</a>

Paginatorでの1階層下げた時の挙動について

それでは、HtmlHelper::linkでやった方法で、Paginatorもできるのか。実は出来ない。困ったことに、URLを生成する関数で、array('base' => false)の部分が消されてしまう。

 $url = array_merge(Set::filter($url, true), array_intersect_key($url, array('plugin' => true)));

http://api13.cakephp.org/view_source/paginator-helper/#l-362

消される部分が、Set::filter($url, true)の部分ではfalseが削除されてしまうし、array_intersect_key($url, array('plugin' => true))の部分でもpluginというキーでないと削除されてしまう。

しょうがないので、以下のように指定してお茶を濁した。うーむ。

<?php echo $this->Paginator->next('>>', array('url' => array('base' => 0, 'plugin' => null)), null, array('class' => 'disabled')); ?>

以下のようになる。base:0が余計につく。

<a href="/mobile/tmcviewers/history/page:3/base:0" class="next">&gt;&gt;</a>

最終的にこの方法での改良を諦めました

別にうまくいったのですが、わけあって他の方法を取りました。あしからず