3月
31
2010

[CakePHP]counterCacheがすごく便利なのでメモ


例えば以下の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したらどうなるか?
こういったことは検証していないので、もしやってみた方は教えていただけると嬉しいです。

  1. UserLogをベースに、group by user_idで取得することもできますよね。 検証はしてませんが、なんとなく重くなりそうな気がするので僕はUserモデルをベースにしてます。 []
  2. user_logsじゃないので注意!複数形じゃなく単数形で”user_log”_countね []

▼Advertisement

【Webサービスを作ろう!好評連載中!】このエントリーをはてなブックマークに追加 はてなブックマーク -
⇒ #1 挫折しないウェブサービス開発のための4つの心構え
Webサービス、Webアプリケーション開発に興味のある方は必見です!

【2月のイチオシ記事】このエントリーをはてなブックマークに追加 はてなブックマーク -
⇒ 社長になった私がお金にならないデータベースサイトを作った7つの理由

Written by suzuki in: メモ,リファレンス | タグ: ,

1件のコメント

  • designarea より:

    この記事のおかげでモデルにSQL文書いたりして処理していたものがだいぶ省略できました。参考になる記事ありがとうございました

RSS feed for comments on this post.


| I have been indebted to Aeros Theme. |