背景
性能問題などによって発行するSQLを変更したいが、出力形式を変えたくない。
そのような場合が、多々あると思います。
CakePHP2を使っている場合、ModelのafterFindメソッドをoverrideすれば検索結果の構造変更などは実現できますが、特定の画面の特定のfindの時だけ変えたいような場合はafterFindだと影響範囲が広すぎます。
そのようなケースでは、findに渡すパラメータにtypeを指定し、そのtypeに該当するfindメソッドをModelに定義することで前処理や後処理を追加することができます。
実装サンプル
class Book extends AppModel {
// typeを$findMethodsというプロパティに登録します
public $findMethods = ['rented' => true, 'bought' => true];
/**
* type=rentedに対応するfindメソッド.
* 命名規則は_findの後にtypeの先頭を大文字にした文字列とする.
*
* @param string $state "before"か"after"が設定される
* @param mixed $query find呼び出し時のオプションが設定される
* @param array $results "after"の場合に検索結果が設定される
* @access protected
* @return array
*/
protected function _findRented($state, $query, $results = array()) {
// 検索オプションを更新する場合など
if ($state === 'before') {
$query['conditions']['rented'] = 1;
return $query;
}
// 検索結果を更新する場合など
if ($state === 'after') {
$customResults = [];
foreach ($results as $result) {
// 結果を加工
$result['Book']['full_name'] = '借り物:' . $result['Book']['name'];
$customResults[] = $result;
}
return $customResults;
}
}
/**
* type=boughtを対応したサンプル
*
* @return array
*/
protected function _findBought($state, $query, $results = array()) {
if ($state === 'before') {
// 必要に応じて処理を記載
return $query;
}
if ($state === 'after') {
// 必要に応じて処理を記載
return $results
}
}
/**
* type=rentedを指定してfindを呼び出すサンプル.
*
* @return array
*/
public function retrieveRentedBooks() {
// typeにrentedを指定するとフレームワークが_findRentedを呼び出す
return $this->find('all', [
'type' => 'rented'
]);
}
}