findの前後に処理をフックしてdb検索の挙動を変更
Cakephpでおなじみのデータベース関数findの挙動を変更するには、モデル内でbeforeFindとafterFindを定義することで可能になります。
beforeFind
beforeFindでは、コントローラ側で定義したfindのconditionsの内容をdbにアクセスする前に変更することができます。以下の例では、$queryDataのデータ構造を変更してprimarykeyを変更している例です。
function beforeFind($queryData) { $queryData['conditions']['Product.uid'] = $queryData['conditions']['Product.id']; unset($queryData['conditions']['Product.id']); return $queryData; }
このfindを成立させるためには、コントローラ側で
$this->Product->primaryKey = ‘uid’;
のようにして主キーを変更しておく必要があります。
afterFind
afterFindでは、データベース検索後のデータ($results)を操作する場合に利用できます。以下の例では、上のbeforeFindの例でprimarykeyを変更してfind操作を行ったので、コントローラ側にfindの結果を返す前にデータ構造を正規の状態に戻す操作を行っています。
function afterFind($results) { $results_c = count($results); for( $i = 0; $results_c > $i; $i++ ) { if( $results[$i]['Product']['uid'] ) { $tmp_id = $results[$i]['Product']['id']; $tmp_uid = $results[$i]['Product']['uid']; $results[$i]['Product']['uid'] = $tmp_id; $results[$i]['Product']['id'] = $tmp_uid; } } return $results; }
beforeFindとafterFindを利用すれば、find実行前にconditionsの状態を変えたり、find実行後にデータを操作してコントローラに返すことが可能になります。
個人的には、システムの拡張に伴い仕方なく利用する機能だと考えています。findのフックを利用することでfind関連の複雑さは増加しますので、最初から積極的に利用する機能ではないです。