CakePHP

CakePHP2.1 paginatorのsortを2カラム以上(複数)で実行する方法

CakePHPのページング機能を大変ありがたく利用させてもらっていますが、ビューでPaginator->sort()を使うとそのカラムだけの並び換えになります。一覧表を作成するとき、例えば日付順・顧客ID順などと表示したいときがあります。しかしいろいろと探して見ましたが上手い方法が見つかりませんでした。

以下の方法はコアコンポーネントを置き換える方法なのでお勧めできませんが、たった1行手を加えるだけで目的とする複数カラムの並び換えができるので、「どうしても!」と思う方は試してみて下さい。

Summary

コアコンポーネント「PaginatorComponent.php」のソース1行を書き換えます。アップデートで変更したソースが消えてしまわないように、「app/Controller/Component」にコピーしてそれに手を加えます。

並び換えはビューで指定されたカラムを優先し、コントローラの「$paginate」で指定したソート条件を加えるようにします。複数カラムのソートが必要なければ、「paginate()」をコールする前にパラメータを削除すればOKです。

How To

今回対象とするCakePHPのバージョンは2.1です。「PaginatorComponent.php」の「validateSort()」メソッドの中に、「named」パラメータで渡されたソート条件を検索条件にセットしている箇所が333行目にあります。

public function validateSort($object, $options, $whitelist = array()) {
    if (isset($options['sort'])) {
        $direction = null;
        if (isset($options['direction'])) {
            $direction = strtolower($options['direction']);
        }
        if ($direction != 'asc' && $direction != 'desc') {
            $direction = 'asc';
        }
        $options['order'] = array($options['sort'] => $direction);
    }

    if (!empty($whitelist) && isset($options['order']) && is_array($options['order'])) {
 :

変更は、

$option['order'] = array($options['sort'] => $direction);

$options['order'] = array_merge(array($options['sort'] => $direction), $options['order']);

とすればOKです。