public function run() { $modelName = $this->modelName; $ratingArray = AggregateRating::find()->select('target_id, rating')->where('model_id = :modelId', ['modelId' => Rating::getModelIdByName($modelName)])->orderBy('rating DESC')->limit($this->limit)->asArray()->all(); $ids = ArrayHelper::getColumn($ratingArray, 'target_id'); $models = $modelName::find()->joinWith('aggregate')->where(['in', $modelName::tableName() . '.' . $modelName::primaryKey()[0], $ids])->orderBy('rating DESC')->all(); return $this->render('topRated', ['models' => $models, 'title' => $this->title, 'titleField' => $this->titleField, 'path' => $this->path]); }
/** * @param string $modelId Id of model * @param integer $targetId Current value of primary key */ public static function updateRating($modelId, $targetId) { $likes = static::find()->where(['model_id' => $modelId, 'target_id' => $targetId, 'value' => self::VOTE_LIKE])->count(); $dislikes = static::find()->where(['model_id' => $modelId, 'target_id' => $targetId, 'value' => self::VOTE_DISLIKE])->count(); if ($likes + $dislikes !== 0) { // Рейтинг = Нижняя граница доверительного интервала Вильсона (Wilson) для параметра Бернулли // http://habrahabr.ru/company/darudar/blog/143188/ $rating = (($likes + 1.9208) / ($likes + $dislikes) - 1.96 * SQRT($likes * $dislikes / ($likes + $dislikes) + 0.9604) / ($likes + $dislikes)) / (1 + 3.8416 / ($likes + $dislikes)); } else { $rating = 0; } $rating = round($rating * 10, 2); $aggregateModel = AggregateRating::findOne(['model_id' => $modelId, 'target_id' => $targetId]); if (null === $aggregateModel) { $aggregateModel = new AggregateRating(); $aggregateModel->model_id = $modelId; $aggregateModel->target_id = $targetId; } $aggregateModel->likes = $likes; $aggregateModel->dislikes = $dislikes; $aggregateModel->rating = $rating; $aggregateModel->save(); }
/** * @inheritdoc */ public function getAggregate() { return $this->owner->hasOne(AggregateRating::className(), ['target_id' => $this->owner->primaryKey()[0]])->onCondition(['model_id' => Rating::getModelIdByName($this->owner->className())]); }