CakePHP Behaviorでモデルのメソッドキャッシュ with find() オーバーライド
元ネタは以下2つのエントリー。
http://blog.katsuma.tv/2009/04/cakephp_model_cache.html
車輪の再発明というわけではないですが、好みに併せて少し改変。
メモ代わりに残します。
目的
サイト全体の高速化
View cache を利用出来ない部分が主
メリット/デメリット
http://blog.katsuma.tv/2009/04/cakephp_model_cache.html
上記ページに分かり易く記載されているので、ここでは簡潔に。
最大のメリットは
キャッシュを意識することなく、クエリーキャッシュを利用することが出来る事。
逆にデメリットは
完全な最適化が行われるわけではないので、最も早くなるわけではない。
ま、これは個別に対応すればよいという整理。
導入手法
1)CacheBehavior を導入
ソースは以下から。
http://www.exgear.jp/blog/2008/11/cakephp12-behavior%E3%81%A7%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%82%92%E8%A1%8C%E3%81%86/
動作させるために、Model に Behavior 属性を記載。
怠慢な私は、app_model.php に記載しちゃってます。
2)find() をオーバーライド
app_model.php 上で find() をオーバーライド。
以下のような形で、キャッシュでフォルト設定から Duration(キャッシュ有効時間)を引き継いでます。
また、明示的に Duration を指定したい場合に備えて、 $options 内に属性を勝手に定義。まめにキャッシュをクリアしたいコンテンツなどで利用してます。
<?php /** * Find over write. * モデルキャッシュを利用するために * * @link http://blog.katsuma.tv/2009/04/cakephp_model_cache.html */ function find($type, $queryData = array()) { switch ($type) { case '任意のタイプ': return $this->find('all', Set::merge(array("conditions"=>array('任意の検索条件')), $queryData)); default: // Set cache duration if (is_array($queryData) && isset($queryData['cacheDuration']) && !empty($queryData['cacheDuration'])) { $cacheDuration = $queryData['cacheDuration']; unset($queryData['cacheDuration']); } else { $cacheSetting = Cache::settings(); $cacheDuration = $cacheSetting['duration']; } if (!is_numeric($cacheDuration)) { $cacheDuration = strtotime($cacheDuration) - time(); } if ($cacheDuration < 1) { return false; } // Call cache method $args = array($type, $queryData); if ($this->Behaviors->attached('Cache')) { if($this->cacheEnabled()) { return $this->cacheMethod($cacheDuration, __FUNCTION__, $args); } } // Case normal find. The model does not have cache behavior. return parent::find($type, $queryData); } } ?>
3)Model->field() で Warning が。
検索条件を指定する部分は
<?php $hoge_id = $this->field('hoge_id', array('id' => $id)); ?>
では駄目でした。
<?php $hoge_id = $this->field('hoge_id', array('Fuga.id' => $id)); ?>
という形で、Model 名を明示的に指定すればOK
親クラスのメソッドを使ってるからだろと。
なぜ動かない?
実装の途中で不可解な事象に遭遇。何故だろう?
最終的に
<?php return parent::find($type, $queryData); ?>
とした部分。
情報ソースのサイトでは
<?php $parent = get_parent_class($this); return call_user_func_array(array($parent, __FUNCTION__), $args); ?>
となっていた。
ソースを眺めた時点では、特に気にする事はなかったのだが。。。
いざ実行してみると、真っ白画面が。。。
インスタンス参照の問題?