Рассчитать новое среднее значение после сохранения (или что-то лучше?) В CakePHP
Я строю систему рейтинга, где пользователь может оценить что-то от 1 до 5 звезд.
Мне было интересно, есть ли способ автоматически рассчитать все оценки конкретного элемента (из таблицы рейтингов, где model='x' и foreign_key='y') на afterSave
или что-то подобное.
Я могу сделать это в Rating_controller просто отлично... просто подумал, что это может быть более идеальным, чтобы сделать это автоматически в модели. Кто-нибудь может указать мне правильное направление для этого?
Мне очень хотелось бы услышать, что в CakePHP есть какая-то настройка ассоциации, которая позволяет ему сделать это для вас - что-то вроде:
//Rating model
var $belongsTo = array(
'Restaurant' => array(
'averageValue' => 'rating
)
);
Но - я уверен, что многого просят:)
2 ответа
Если вы хотите сохранить среднее значение в поле в таблице элементов, то AfterSave, вероятно, будет лучшим решением на данный момент.
Единственное, что торт может автоматически сделать для вас, - это отслеживать, сколько оценок имеет элемент (counterCache), но не другие агрегатные функции.
VirtualField может быть хорошим, но я никогда не использовал это для агрегатных функций, поэтому я не уверен. Кроме того, если ваши рейтинги меняются не часто, это приведет к ненужной работе в системе.
В рейтинговой модели:
function afterSave($created){ $avgValue = $this->Query('SELECT AVG(rating) as rating FROM ratings WHERE ratings.restaurant_id = '.$this->restaurant_id); $this->Restaurant->updateRatingAverage($this->restaurant_id,$avgValue[0][0]['rating']); }
В модели ресторана
function updateRatingAverage($id,$avg){ $this->id = $id; $this->field('your_average_field_here',$avg); }
Возможно, вы захотите зарегистрировать $ avgValue, чтобы увидеть, как он структурирован, но я думаю, что понял это правильно.
Мне нужно написать и ответить, потому что я пока не могу комментировать.
Итак, ваши (например) рестораны имеют много рейтингов? Попробуйте VirtualField в модели ресторанов, где вы рассчитываете рейтинг каждый раз, когда рестораны выбираются из базы данных. Там может быть необходимость для GROUP BY, как упомянуто ypercube, если вам нужно использовать AVG().