我有一个用户模型和一个消息模型。
消息模型与用户模型链接两次,如下所示:
public $belongsTo = array(
'UserSender' => array(
'className' => 'User',
'foreignKey' => 'sender_id',
'counterCache' => array(
'messages_sent_count' => array(
'is_deleted' => FALSE
)
)
),
'UserRecipient' => array(
'className' => 'User',
'foreignKey' => 'recipient_id',
'counterCache' => array(
'messages_received_count' => array(
'is_deleted' => FALSE
),
'messages_unread_count' => array(
'is_deleted' => FALSE,
'is_read' => FALSE
)
)
),
'Operator' => array(
'className' => 'Operator',
'foreignKey' => 'operator_id'
)
);
除了用户模型,消息模型也$belongs属于运营商模型。Operator模型与用户的消息计数无关,但其表仍在计数查询中加入,如调试所示:
'query' => 'SELECT COUNT(*) AS `count` FROM `database`.`messages` AS `Message` LEFT JOIN `database`.`operators` AS `Operator` ON (`Message`.`operator_id` = `Operator`.`id`) LEFT JOIN `database`.`users` AS `UserSender` ON (`Message`.`sender_id` = `UserSender`.`id`) LEFT JOIN `database`.`users` AS `UserRecipient` ON (`Message`.`recipient_id` = `UserRecipient`.`id`) WHERE `Message`.`is_deleted` = '0' AND `Message`.`sender_id` = 389',
'params' => array(),
'affected' => (int) 1,
'numRows' => (int) 1,
'took' => (float) 394
为了简单起见,我实际上排除了Message模型$belongsTo的另一个模型,但上面的查询显示了问题。
counterCache函数只是为了更新计数器而执行一个相当昂贵的查询。有没有一种方法可以覆盖或调整counterCache方法,使其不联接查询中不相关的表?
我现在无法测试它,但由于Model::updateCounterCache()
使用的recursive
设置是根据是否为计数器缓存字段定义了条件进行硬编码的,因此更改此设置的唯一方法(除了完全重新实现Model::updateCounterCache()
之外(可能是修改Message
模型的Model::_findCount()
或Model::beforeFind()
中的count
查询。
public function beforeFind($query) {
// ... figure whether this is the count query for updateCounterCache,
// maybe even try to analyze whether the passed conditions require
// joins or not.
if(/* ... */) {
$query['recursive'] = -1;
}
return $query;
}
根据您实际需要的控制量,可容纳行为可能也会起作用,它会将recursive
设置为-1
,以防没有包含内容通过
$Message->contain(); // === recursive is being set to -1 in before find callback
$Message->delete(123);