例えば以下の2テーブルがあったとして・・・
ユーザの情報をもつユーザテーブル
users(Userモデル)
ユーザーがページを開くたびに保存されるログ(apacheのアクセスログみたいなものだと思ってもらえば)
もちろんuser_idというフィールドを持っている
user_logs(UserLogモデル)
このとき、User.idごとのページビュー(UserLogのレコード数)を取得したい場合はどうしますか?
僕の場合はコントローラで、
$bind = array( "hasMany" => array( "UserLog" => array( "fields" => array("count(id) as pv"), "conditions" => array("1 = 1 group by UserLog.id") ) ) ); $this->User->bindModel($bind);
こんな感じで、取得していました。*1
でも、面倒だし、出力されるデータも
↓users = array( "User" => // 省略 "UserLog" => array( "0" => array( // 省略 "UserLog" => array( "0" => array( "click" => // ここでやっとクリック数 ) ) ) ) );
すごく深くなってしまう。むだですよね。
counterCacheを使うと
usersテーブルに「user_log_count」*2 というフィールを追加。
UserLogモデルにbelongsToアソシエーションを追加して、counterCacheをtrueに
var $belongsTo = array( "User" => array( "counterCache" => true, ), );
そうすると・・・
なんということでしょう!
UserLogにデータが追加されるたびにUser.user_log_countの数字がインクリメントされ、カウントが反映されます。
これでもうカウントを取得するためにUserLogをバインドする必要も無く、User単独でカウントが取得できるというわけ。
すごく便利でしょ!?
ちなみに
UserLogのレコードをdeleteしたらどうなるか?
UserLog.user_idを別のuser_idにupdateしたらどうなるか?
こういったことは検証していないので、もしやってみた方は教えていただけると嬉しいです。
コメント
この記事のおかげでモデルにSQL文書いたりして処理していたものがだいぶ省略できました。参考になる記事ありがとうございました