アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

PEAR Pagerのトラブル回避

こんにちは、牧野です。今回はphpの軽めな話題です。
最近、小さなシステムの作り直しをやっていました。フレームワークは使わず、smartyPEARを少し使った以外は全部自前で作ったのですが、そういうのも作っていて楽しかったりします。
その中でPEARのPagerを使いました。Pagerは便利なのですが、はまりやすいポイントがいくつかあると思います。今さらな感じもしますが、今回はそんな問題点とその回避方法を簡単にまとめました。
Pagerの使い方はどこか他のページを見て下さい、ということで。。。

Pagerのマニュアル

その1 post or get
factoryメソッドに渡す配列引数の中に「httpMethod」がありますが、通常はここで指定した方式のパラメータしか引き継いでくれません。いろいろなページからpagerのページに来る場合は注意する必要があります。僕は初めて使った時に失敗しました。
簡単に回避するには、factoryメソッド実行前に


$_GET = $_REQUEST;  //httpMethodがgetの場合
$_POST = $_REQUEST; //httpMethodがpostの場合

としておくか、factoryメソッドに渡す配列引数の「importQuery」をfalseにして、「extraVars」を$_REQUESTまたは引き継がせたいパラメータ配列にしてやります。
importQueryはパラメータを自動で引き継ぐかどうかの設定で、デフォルトはtrueです。extraVarsに連想配列を指定すると、その配列がパラメータとして付け加えられます。


その2 パラメータの値に日本語が含まれている場合
パラメータの値に日本語のようなマルチバイト文字列が含まれていると、ページングのリンクがおかしくなる場合があります。
httpMethodがgetかpostか、内部エンコーディング、出力エンコーディングが何かによって対応が変わってきます。

getの場合
内部エンコーディングと出力エンコーディングが同じ場合は大丈夫です。
違う場合は、importQueryをfalseにし、extraVarsに渡すパラメータ配列を出力エンコーディングに直しておくのがよいと思います。

postの場合
postの場合は、内部、出力エンコーディングに関係なく問題が起こります。
postでもパラメータ文字列が全部urlencodeされて出力されてしまうからです。
一番簡単な対応は、Pager/Common.phpの930行目あたり、_generateFormOnClickHelper()メソッド内



            // am I foreetting any dangerous whitespace?
            // would a regex be faster?
            // if it's already encoded, don't encode it again
            if (!$this->_isEncoded($escapedData)) {
                $escapedData = urlencode($escapedData);
            }
            $escapedData = htmlentities($escapedData, ENT_QUOTES, 'UTF-8');

の部分を


            // am I foreetting any dangerous whitespace?
            // would a regex be faster?
            // if it's already encoded, don't encode it again
            //if (!$this->_isEncoded($escapedData)) {
                //$escapedData = urlencode($escapedData);
            //}
            $escapedData = htmlentities($escapedData, ENT_QUOTES, 'UTF-8');

のようにコメントアウトします。内部エンコーディングUTF-8でない場合はhtmlentitiesの第3引数も直しておきます。

あとおまけですが、パラメータに「submit」という名前のものがあってhttpMethodがpostだと、Firefoxでは動きません。これはjavascriptの問題です。

内部エンコーディングと出力エンコーディングを同じにして、httpMethodをgetにしておけば、ほとんど問題は起こらなさそうです。