我正在尝试将基于IP的投票系统迁移到基于用户的登录投票系统,并希望保留旧的投票/喜欢。所以我将旧系统like_count复制到我的引号表中的一列中。
引用表
投票表
我根据投票表中的投票,在引号表中为like_count实现了反向缓存行为。但是,例如,如果我现在将id为145的报价投票,那么like_count将跳转到1而不是3616,因为在投票表中只有1票对报价id 145。
那么CounterCache行为是否有一种方法可以考虑到like_count列并从那里开始而不是从0开始?
答案 0 :(得分:1)
你必须自己解决这个问题,这种情况没有开箱即用的功能。
我建议将旧投票存储在一个单独的列中,比如legacy_like_count
,然后在您读取数据时计算新旧投票/喜欢的总和,手动或者为使用虚拟属性的示例,如:
protected $_virtual = ['total_like_count'];
public function _getTotalLikeCount() {
return $this->_properties['like_count'] + $this->_properties['legacy_like_count'];
}
或者如果您想要存储在数据库中的总计数,请使用计数器缓存行为支持的回调功能,您可以在其中构建计算新投票的自定义查询,并添加旧的喜欢数量,例如:
[
'Quotes' => [
'like_count' => function (
\Cake\Event\Event $event,
\Cake\Datasource\EntityInterface $entity,
\Cake\ORM\Table $table
) {
// $event = Model.afterSave or Model.afterDelete (VotesTable)
// $entity = Vote
// $table = VotesTable
$votes = $table
->find()
->where([
'Votes.quote_id' => $entity->get('quote_id')
])
->count();
$quote = $table->Quotes->get($entity->get('quote_id'));
return $votes + $quote->get('legacy_like_count');
}
]
]
您可能也可以在SQL级别上进行计算,类似于以下内容:
$query = $table->Quotes->find();
return $query
->select([
'totalVotes' => $query
->newExpr()
->add([
'Quotes.legacy_like_count',
$query->func()->count('Votes.id')
])
->setConjunction('+') // use tieWith() in CakePHP < 3.4
])
->leftJoinWith('Votes')
->where([
'Quotes.id' => $entity->get('quote_id')
])
->groupBy('Quotes.id');
会产生类似于以下内容的SQL,如果在示例中返回,则会在like_count
列的更新过程中用作子查询:
SELECT
(Quotes.legacy_like_count + COUNT(Votes.id)) AS totalVotes
FROM
quotes Quotes
LEFT JOIN
votes Votes ON Quotes.id = Votes.quote_id
WHERE
Quotes.id = :c0
GROUP BY
Quotes.id
请注意,这是所有未经测试的示例代码!
另见