A little tip about counterScope

One of many cool CakePHP’s features is the Counter Cache.

From the manual: “This function helps you cache the count of related data. Instead of counting the records manually via find(’count’), the model itself tracks any addition/deleting towards the associated $hasMany model and increases/decreases a dedicated integer field within the parent model table.”

So if you have Forum with Posts, you can keep track of how many posts are there in a given forum by tracking this data in the “forums” table, which certainly speeds things up and takes a little load off your DB.

One feature that is not (yet) very well documented is the ability to provide a counterScope. It essentially allows you to specify a simple condition, which tells the model when to update (or when not to, depending on how you look at it) the counter value.

Using our Post model example, we can specify it like so:


class Post extends AppModel {
        var $name = 'Post';
        var $belongsTo = array('Forum'=>array(
                                              'counterCache'=>true,
                                              'counterScope'=>array('Post.deleted'=>0)));

    }

This means that counter will only be updated for posts that are active: 'deleted'=>0.

Also, it is implied in this example that you have some admin tool, which lets you do soft deletes of your posts (i.e. set the “deleted” field to 1)…

Something simple, like this:


function delete($id = null) {
   if($id) {
        $this->Post->id = $id;
        $this->Post->saveField('deleted', 1);
   }
}

Guess what? Cake is going to update your counter field in the forums table, when you deactivate a post in this manner.

Brilliant stuff, I tell ya…