CakePHP

カスタムfindを使ってpaginateをカスタマイズする方法

ページナビゲーション機能を提供するPaginatorは簡単に利用できてとても便利ですが、検索結果に対して処理をかけるオプションが用意されていません。
ですが、Paginatorは内部でfindを使っており、findは比較的カンタンにカスタマイズすることができるので、Paginatorの返却値を加工することができます。

find メソッドはカスタム動作を定義することができます。
findの第1引数に first や all や、任意に定義したカスタム値を指定して返却値の形式を指定することができます。
例えば、Userモデルの find に special というカスタム値をそれに関連するメソッドを追加するには、下記のようにします/p>

まず、Userモデルの Model::$findMethods 変数にカスタム値を追加します。

public $findMethods = array('special' =>  true);

次に _find とfind種別名を組み合わせた _findAvailable メソッドを定義します。

protected function _findSpecial($state, $query, $results = array()) {
    if ($state == 'before') {
        $query['conditions']['User.gender'] = 1;
        return $query;
    } elseif ($state == 'after') {
        return $results;
    }
    return $results;
}

これで ->find("special") で呼び出せるようになります。

$this->User->find("special");

_find[Type] メソッドは上記の例のように3つの引数を受け取ります。
1つめはクエリの実行状態を表し、before、after の値があります。beforeはクエリの実行前を示す値で、このステータスの時はクエリ実行前に処理されます。
例えば、下記ではクエリに User.gender==1 という条件式を追加してます。

if ($state == 'before') {
    $query['conditions']['User.gender'] = 1;
    return $query;
}

beforeブロックの返却値として $query を返す必要があります。

after はクエリ実行後を示す値で、このステータスの時はクエリ実行後に処理されます。
クエリ後の取得データを加工したい際などに便利です。

if ($state == 'after') {
    foreach ( $result as $key => $val ){
        $result[$key]['img'] = '/img/men.png';
    }
    return $result;
}

afterブロックの返却値として $result を返す必要があります。

以下のようにして、カスタムfindでページネーションをすることも出来ます。

public function index() {
    $this->paginate = array('pagination');
    $articles = $this->paginate();
}

上記のように $this->paginate 変数にカスタムfindをセットすることで、その結果が pagination のfind結果になります。

関連記事