class Raits extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'raits';
}
public function rules()
{
return [
[['book_id', 'user_id', 'rateNum'], 'safe'],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
[['book_id'], 'exist', 'skipOnError' => true, 'targetClass' => Book::className(), 'targetAttribute' => ['book_id' => 'id']],
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'book_id' => 'Book ID',
'user_id' => 'User ID',
'rateNum' => 'Rate Num',
];
}
public function behaviors()
{
return [
'blameable' => [
'class' => BlameableBehavior::className(),//устанавливаем id юзера
'createdByAttribute' => 'user_d',
'updatedByAttribute' => null,
],
];
}
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
public function getBook()
{
return $this->hasOne(Book::className(), ['id' => 'book_id']);
}
}
public function actionOne($id)
{
$book = Book::findOne(['id' => $id]);
if (Yii::$app->request->isPost && Yii::$app->request->isAjax && Yii::$app->request->post('rait')){
$rait = Yii::$app->request->post('rait');//оценка пользователя
$res = [];
if(!Yii::$app->user->isGuest){
//есть ли запись о голосовании на материале у данного пользователя
$userRaits = Raits::find()
->andWhere(['book_id' => $id])
->count();
//если пользователь уже голосовал выводим сообщение и далее не выполняем
if($userRaits){
$res['message'] = 'Этот голос не учитывается. Вы уже проголосовали ранее...';
return json_encode($res, JSON_NUMERIC_CHECK);
}
//Если новый голос пользователя, записываем в бд
$newRait = new Raits();
$newRait->book_id = $id;
$newRait->rateNum = $rait;
$newRait->save();
/**
* Вычисляем общий рейтинг с учетом изменений
*/
//выбираем все голоса по данной записи
$allRaits = Raits::find()->where(['book_id' => $id])
->select('rateNum');
$allUsers = $allRaits->count();//сумма всех учетных записей пользователей к дан. материалу (1а запись - 1 пользователь)
$sumVotes = $allRaits->sum('rateNum');//сумма всех оценок пользователей к дан. материалу
$totalRating = round($sumVotes / $allUsers, 2);// округляем до сотых
//записываем вычесленный рейтинг в таблицу книги в поле rating
$inst = Book::findOne($id);
$inst->rating = $totalRating;
$inst->ratingVotes = $allUsers;
$inst->save();
//возвращаем новый рейтинг в вид
$res['rating'] = $inst->rating;//передаем вычесленный рейтинг по материалу
$res['ratingVotes'] = $inst->ratingVotes;//передаем сумму всех голосов по материалу
return json_encode($res, JSON_NUMERIC_CHECK);
}
}
$countComments = Comments::countComments($id);
return $this->render('one', ['book' => $book, 'countComments' => $countComments]);
}
<?php //echo $institution->rating;
echo StarRating::widget([
'name' => 'rating_1',
'model' => $book,
'attribute' => 'rating',
//'value' => 3,
'pluginOptions' => [
//'displayOnly' => true,//звезды только для показа, но не активны
'theme' => 'krajee-svg',
'stars' => 5,
'step' => 1,
'min' => 0,
'max' => 5,
'showClear' => false,// (знак "кирпич")
'showCaption' => true,//без подписи количества выбранных
'size' => 's',//mili
'defaultCaption' => 'оценка {rating}',
'starCaptions' => [
0 => 'Extremely Poor',
1 => 'оценка 1',
2 => 'оценка 2',
3 => 'оценка 3',
4 => 'оценка 4',
5 => 'оценка 5',
],
],
'pluginEvents' => [
//когда кликаем на звезды всплывает это событие, которое и обробатываем
'rating.change' => "function(event, value, caption) {
$.ajax({
type: 'POST',
url: '".Url::to("book/one")."',//адрес контроллера и экшена. Так как вид вызван из того же экшена, что и обработка этого запроса, тооставляем пустым или пишем - controller/action
data: {'rait': value},// value - число выбранных звезд
cache: false,
success: function(data) {
var data = jQuery.parseJSON(data);//конвертируем json обьект, что передаем из php в обьект jquery
var inputRating = $('#book-rating');
if (typeof data.message !== 'undefined') {
console.log(data.message);
inputRating.rating('reset');//очищает рейтинг до значения в бд
$('#myModal-geo .modal-body strong').text(data.message);//забиваем сообщение в модальное окно
$('#myModal-geo').modal();//вызываем виджет модального окна
}else{
$('#numRait').text(data.rating);//обновляем цыфры рейтинга в тегах на странице
$('#numVotes').text(data.ratingVotes);//обновляем цыфры кол-ва голосов в тегах на странице
inputRating.rating('refresh', {disabled: true, showClear: false, showCaption: true});//добавляет рейтинг и блокирует повторное нажатие
}
}
});
}",
],
]);
?>