counterCache (HABTMでも)

posted 2009-07-03 | written by mon_sat

カウンターキャッシュとは、hasManyしている関連Modelがあるとき、そのModelの件数を元Modelに保持しておく機能です。
http://book.cakephp.org/ja/view/81/belongsTo

たとえばArticle hasMany Comment というコメントを複数ぶらさげている記事があったとき、コメントの件数をArticle Modelに持たせることができます。
これによりわざわざコメントModelを取得することなく、コメントの件数を(記事一覧ページに)表示させるといったことが可能です。
データベースの構造からすると冗長なデータの持ち方ともいえますが、フィールドをひとつ増やすことでDBへのアクセスを減らすことが見込めますので、ぜひ積極的に活用したい機能です。

使い方は簡単です。

HABTMのcounterCacheは後述します。

まず、上記の例でArticleにあたるModelにフィールドを追加します。

  • model_name_count    integer

上記の例では comment_count です。

つぎに、関連先のModelのアソシエーションを以下のように変更します。

# models/comment.php
var $belongsTo = array(
    'Article' => array(
        'counterCache' => true,
        'counterScope' => '',
    ),
);

これだけです。
これだけで、コメントがadd , edit ,delete されるたびに、紐付いたコメントの件数がArticleに書き込まれます。

実際にデバッグモードで発行されるSQL文を確認すると、insert等のあとにselect count(*) して、Articleをupdateしているのがわかります。

HABTMでcounterCacheを使う

さて、非常に簡単なcounterCacheですが、残念ながらHABTMでは使えません。
Article hasAndBelongsToMany Tag となっているとき、ArticleにはTagの件数を、TagにはArticleの件数を持っておきたいというのが人情です。

タグ(tag)付けされた、複数の記事(article)がある状況

そこで登場するのが、bakeryに投稿されたこのビヘイビア(CounterCacheHabtmBehavior)です。
このビヘイビアのすばらしいところは、それぞれのModelに xxx_count というフィールドを用意し、$actsAsで指定すれば、それだけで良いということです。

# model
// 両方のモデルに記述します
// カウントはxxx_countというフィールドが存在しているときのみ実行されます
var $actsAs = array('CounterCacheHabtm');

なお、片方のModelのみに xxx_count を用意した場合も、何の設定も必要なく、動作いたします。
(xxx_countが存在しない場合はカウントされません)

プロフィール

@mon_sat

CakePHPをよく利用しています。

理解の浅かった半年前と、何も知らなかった一年前の自分への教科書として書いています。
当たり前のことも平易に。

RSS2.0

カテゴリ別エントリ一覧

タグ別エントリ一覧

アーカイブ