読者です 読者をやめる 読者になる 読者になる

ほげほげ(仮)

仮死状態

CakePHPのpaginateでpage:〜以外のパラメータをエラーにする

PHP

んー、タイトルだけでは内容がイマイチ伝わらないですね

現象

routes.phpでルーティングを制御している場合ですが、paginateを使うページには次のような定義をするかと思います。

<?php
Router::connect('/hoge/*', array('controller' => 'hoge', 'action' => 'index'));
?>


一応コレでも問題ないですが、次のようなURLでも通ってしまいます。

/hoge/foo
/hoge/foo/page:2
/hoge/foo/page:2/bar
/hoge/hoge/hoge/hoge/hoge/hoge/hoge/page:2/bar

なんか気持ち悪いのでなんとかしたいと思います


コントローラーで$this->passedArgsを使って判定します。

$this->passedArgsは$this->params['named']と$this->params['pass']の値が格納されてます。

$this->params['pass']

routes.phpに設定している以外の文字列はココに格納されます。

例えば

/hoge/<span style="color:#FF0000;">foo</span>

この場合は$this->paramsの値は

Array
(
    [named] => Array
        (
        )
    <span style="color:#FF0000;">[pass] => Array
        (
            [0] => foo
        )</span>
    [controller] => hoge
    [action] => index
    [plugin] => 
    [form] => Array
        (
        )
    [url] => Array
        (
            [url] => hoge/foo
        )
)

$this->params['named']

「:」がURLにあるとココに格納されます。

例えば

/hoge/<span style="color:#FF0000;">foo:bar</span>

この場合は$this->paramsの値は

Array
(
<span style="color:#FF0000;">    [named] => Array
        (
            [foo] => bar
        )</span>
    [pass] => Array
        (
        )
    [controller] => hoge
    [action] => index
    [plugin] => 
    [form] => Array
        (
        )
    [url] => Array
        (
            [url] => hoge/foo:bar
        )
)

こんな感じです。
もちろんpage:2とかもココに格納されます。

$this->passedArgs

$this->params['pass']と$this->params['named']がマージされたのがココに入ってきます。

例えば

/hoge/<span style="color:#FF0000;">foo</span>/<span style="color:#FF0000;">foo:bar</span>

この場合の$this->passedArgsは

<span style="color:#FF0000;">Array
(
    [0] => foo
    [foo] => bar
)</span>

こういう感じになります。


では、コレを使ってpage以外のパラメータがある場合はエラーにしちゃえばいいかと思います。

コンポーネント作成

一応、コンポーネントとして作成しておきます。


/app/controllers/componentsにcheck_param.phpとして保存します。

<?php
class CheckParamComponent extends Object {

    public function checkPaginate($passedArgs) {

        foreach ($passedArgs as $key => $val) {
            if ($key == 'page') {
                if (!preg_match('/^[0-9]+$/', $val)) {
                    return false;
                }
            } else {
                return false;
            }
        }
        return true;
    }
}
?>

コントローラーから$this->passedArgsを渡してもらって、OKならtrue、ダメならfalseを返します。
page以外のキーがある場合とpageの値が数値ではない場合はfalseを返します。

コントローラーに組み込む

あとはコントローラーで使うだけです。(このソースコードは色々と省略してます)

<?php
class HogeController extends AppController {
    public $components = array('CheckParam');
    public function index() {
        if (!$this->CheckParam->checkPaginate($this->passedArgs)) {
            $this->cakeError('error404');
        }
    }
}
?>

この場合は404エラーにしています。

まとめ

かなり長文になってしまいました><


個人的には結構スマートにできたかなぁって思ってます。
もっと他に簡単な方法があれば教えてくださいm(。−_−。)m