I ran into an issue where I'm writing an upvote/downvote system in CakePHP and wanted to use a cache for votes so I didn't have to recount every vote for every link (very expensive on db calls). I started looking in the CakePHP docs and found: http://book.cakephp.org/view/1033/counterCache-Cache-your-count
It was missing my ability to cache the amount of upvotes and downvotes (named upvote_count and downvote_count) in my database. I figured out a solution with a bit of OOP magic and derping around in the Model.php from Core.
The code I have written is definitely not optimized. If you have better alternatives or code to make it perform better, please comment.
<?php
class Vote extends AppModel {
$name = 'Vote';
$belongsTo = array(
'Item' => array(
'className' => 'Item',
'foreignKey' => 'id',
'counterCache' => true,
),
);
// Overwrite for recounting up/down votes on counterCache
public function updateCounterCache($keys = array(), $created = false) {
$response = parent::updateCounterCache($keys, $created);
// Here is the hook for custom recounts.
$this->recountVotes($this->data['Vote']['item_id']);
// Return the parent::updateCounterCache to make it appear like nothing changed.
return $response;
}
protected function recountVotes($item_id) {
// So this gets a count of the counterCache columns we'd like to make happen.
$record = array(
$this->alias => array(
// WARNING: Direction is an INT(1) instead of TINYINT(1) to allow for a negative in my case.
'upvote_count' => $this->field('COUNT(`id`)', array('direction' => 1, 'item_id' => $item_id)),
'downvote_count' => $this->field('COUNT(`id`)', array('direction' => -1, 'item_id' => $item_id)),
'id' => $item_id,
)
);
// Then update the table it belongs to.
$this->query(sprintf('UPDATE `items` as `Item` SET `Item`.`upvote_count` = %d, `Item`.`downvote_count` = %d WHERE `Item`.`id` = %d',
$record[$this->alias]['upvote_count'],
$record[$this->alias]['downvote_count'],
$record[$this->alias]['id']
));
return true;
}
}
I hope someone finds a use for this ability until CakePHP natively supports it.