chiliec / yii2-vote Goto Github PK
View Code? Open in Web Editor NEWProvides voting for any model :+1: :-1:
License: BSD 3-Clause "New" or "Revised" License
Provides voting for any model :+1: :-1:
License: BSD 3-Clause "New" or "Revised" License
нужно добавить публичное свойство view,
чтобы переопределить на свой вид
Вылезла еще одна проблемка при использовании кеша.
При первом выводе списка виджет отрабатывает верно. Затем список кешируется и вне этого списка остается js-функция vote. Следовательно, при клике на кнопки голосования, функция эта не находится и появляются ошибки.
Правильно, наверно, ее будет вынести в отдельный ассет и подключать (регистрировать принудительно) там, где выводится закешированный список.
Спасибо за полезное расширение!
Писал схожий функционал на CI, обратил внимание на ваше за счет aggregate_rating.
А потому из своих наработок, да и после знакомства с вашим есть что предложить :).
А там, если что-то будет полезное - оформлю в виде отдельного issue.
1.1 Добавить индексы для user_id и model_id
1.2 User_id сделать int. Ip адрес (для гостей) записывать через ip2long()
2.1 По аналогии с action column в GridView разработать несколько свойств
Например:
сейчас в виде генерируется
<span style="cursor:pointer;" onclick="vote('article',9,'like'); return false;" class="glyphicon glyphicon-thumbs-up" id="vote-up-article9">3</span>
хотелось бы получить (из своего)
<a title="нравится" id="up_47839_0" class="it_vote btn btn-success btn-xs" href="http://new.loveorigami.info/world/action">
<span class="glyphicon glyphicon-thumbs-up"></span> <span class="ch">0</span>
</a>
с учетом вышепредложенного
// $up_class = btn btn-success btn-xs
// $up_tpl = <span class="glyphicon glyphicon-thumbs-up"></span> <span class="ch">0</span>
<a title="нравится" id="up_47839_0" class="it_vote $up_class" href="http://new.loveorigami.info/world/action"> $up_tpl </a>
Добавить метод получения IP-адреса в расшифрованном виде.
Наряду с голосованием, еще на сайте присутствует возможность добавления в избранное наиболее понравившееся записи.
Избранное - это как следствие положительного голоса, который пользователь хочет сохранить для себя...
Поэтому предлагаю добавить кнопку "добавить в избранное"...
Принцип поведения для избранного, структуры таблицы и действий аналогичен с голосованием. С той лишь разницей, что намного проще.
Таблица
protected $tableName = '{{%favorites}}';
{
$this->createTable($this->tableName, [
'id' => Schema::TYPE_PK,
'model_id' => Schema::TYPE_SMALLINT . ' NOT NULL',
'target_id' => Schema::TYPE_INTEGER . ' NOT NULL',
'user_id' => Schema::TYPE_STRING . ' NOT NULL',
'date' => Schema::TYPE_INTEGER. ' NOT NULL',
], $tableOptions);
}
в модель добавляем
ALTER TABLE `YOUR_TARGET_TABLE_NAME` ADD (
`fav` smallint(6) NOT NULL,
)
Создаем favAction, где все аналогично, как https://github.com/Chiliec/yii2-vote/tree/master/actions,
окромя пересчета рейтинга (он тут не нужен)
В конфиге
'modules' => [
'vote' => [
'class' => 'chiliec\vote\Module',
// global values for all models
// 'allowGuests' => true,
// 'allowChangeVote' => true,
'allowFav' =>true
'models' => [
// example declaration of models
// \common\models\Post::className(),
// 'backend\models\Post',
// 2 => 'frontend\models\Story',
// 3 => [
// 'modelName' => \backend\models\Mail::className(),
// you can rewrite global values for specific model
// 'allowGuests' => false,
// 'allowChangeVote' => false,
// ],
],
],
],
и если есть параметр 'allowFav' =>true
, тогда в виджете отрисовать кнопку с добавлением в избранное рядом с кнопками голосования
Преимущество в том, что абсолютно аналогичные операции с голосованием и избранным будут в одном модуле, будут использовать один и тот же конфиг с одними и теми же подключенными моделями.
Вместо двух модулей, конфигов, виджетов, вызовов в виде и тп... все будет в одном модуле.
Возможно было бы хорошей идеей интегрироваться, например, с https://github.com/kartik-v/bootstrap-star-rating
Возможность вместо иконок 👍 и 👎 добавлять кастомизируемые надписи.
How can I make the Thumbs up or Thumbs down be highlighted or a different color if current user has voted already?
Опционально добавить показ суммарного рейтинга между кнопками голосования.
Ошибка aggregate
in C:\wamp\www\radiopitut\vendor\chiliec\yii2-vote\widgets\Vote.php at line 118
109110111112113114115116117118119120121122123124 ");
$this->view->registerJs($js, View::POS_END, $this->jsCodeKey);
}
public function run()
{
return $this->render('vote', [
'modelId' => Rating::getModelIdByName($this->model->className()),
'targetId' => $this->model->{$this->model->primaryKey()[0]},
**_'likes' => $this->model->aggregate->likes ?: 0,
'dislikes' => $this->model->aggregate->dislikes ?: 0,
'rating' => $this->model->aggregate->rating ?: 0.0,_**
'showAggregateRating' => $this->showAggregateRating,
]);
}
}
Установил новый виджет.
Получил 105 запросов к базе, вместо 40, как было...
Видимо, что то связано с кешем, но то такое...
Мне то нужно все равно делать сортировку записей по рейтингу.
Вот что получилось
В модель Post добавил relation и объявил константу MODEL_ID
public function getRatings()
{
return $this->hasOne(AggregateRating::className(), ['target_id' => 'id'])->onCondition(['model_id' => self::MODEL_ID]);
}
В модели PostSearch делаю поиск с учетом связи
$query = $this->find();
$query->modelClass = get_parent_class($this);
$query->joinWith('ratings')->published();
Для виджета listVeiw добавил параметр сортировки aggregate_rating
$dataProvider->sort->attributes['aggregate_rating'] = [
'asc' => [AggregateRating::tableName() . '.rating' => SORT_ASC],
'desc' => [AggregateRating::tableName() . '.rating' => SORT_DESC],
'label' => $this->getAttributeLabel('aggregate_rating'),
];
И в самом listView могу теперь получить количество likes, dislikes и rating
Отключил виджет Vote
Количество запросов к базе уменьшилось до 40. А все данные для отрисовки виджета у меня есть
$model->ratings->likes
$model->ratings->dislikes
$model->ratings->rating
Hi, how should look relation model? e.g I have table post. What I need that it working?
Здравствуйте. Подскажите пожалуйста, где поправить следующее? :
в файле widgets/views/vote.php я изменил вид лайков/дизлайков.
<button type="button" class="btn btn-default5">
<span id="vote-up-<?=$modelId?>-<?=$targetId?>" class="fa fa-icons fa-heart" onclick="vote(<?=$modelId?>, <?=$targetId?>, 'like'); return false;" style="cursor: pointer;"> <?=$likes?></span>
</button>
Перед количеством есть
. Когда заходишь на страницу, все хорошо http://joxi.ru/brRjnNQtqwj1r1. Но когда проголосуешь, то пробел пропадает http://joxi.ru/a2XDY0KijxXk2g.
Обновил модуль.
Голосование не работает.
Сейчас запрос идет на www.site.ru/vote
https://github.com/Chiliec/yii2-vote/blob/master/Display.php#L98
так работает
$this->vote_url = Yii::$app->getUrlManager()->createUrl(['vote/default/vote']);
Мне кажется, будет полезно триггерить event после успешного сохранения голоса. Таким образом можно будет подписаться на это событие и сделать, например, логирование действия пользователя, или любую другую логику.
обновился теперь с news_id показывает все но по нажатию на голос за или против пишется всегда: Bad Request
When i try do "php yii migrate/down" i get this error:
Exception 'ReflectionException' with message 'Class m160209_074651_add_indexes_for_aggregate_rating_table does not exist'
in /home/dignity/vendor/yiisoft/yii2/di/Container.php:428
Stack trace:
#0 /home/dignity/vendor/yiisoft/yii2/di/Container.php(428): ReflectionClass->__construct('m160209_074651_...')
#1 /home/dignity/vendor/yiisoft/yii2/di/Container.php(364): yii\di\Container->getDependencies('m160209_074651_...')
#2 /home/dignity/vendor/yiisoft/yii2/di/Container.php(156): yii\di\Container->build('m160209_074651_...', Array, Array)
#3 /home/dignity/vendor/yiisoft/yii2/BaseYii.php(349): yii\di\Container->get('m160209_074651_...', Array, Array)
#4 /home/dignity/vendor/yiisoft/yii2/console/controllers/MigrateController.php(201): yii\BaseYii::createObject(Array)
#5 /home/dignity/vendor/yiisoft/yii2/console/controllers/BaseMigrateController.php(752): yii\console\controllers\MigrateController->createMigration('m160209_074651_...')
#6 /home/dignity/vendor/yiisoft/yii2/console/controllers/BaseMigrateController.php(261): yii\console\controllers\BaseMigrateController->migrateDown('m160209_074651_...')
#7 [internal function]: yii\console\controllers\BaseMigrateController->actionDown(1)
#8 /home/dignity/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#9 /home/dignity/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams(Array)
#10 /home/dignity/vendor/yiisoft/yii2/console/Controller.php(148): yii\base\Controller->runAction('down', Array)
#11 /home/dignity/vendor/yiisoft/yii2/base/Module.php(528): yii\console\Controller->runAction('down', Array)
#12 /home/dignity/vendor/yiisoft/yii2/console/Application.php(180): yii\base\Module->runAction('migrate/down', Array)
#13 /home/dignity/vendor/yiisoft/yii2/console/Application.php(147): yii\console\Application->runAction('migrate/down', Array)
#14 /home/dignity/vendor/yiisoft/yii2/base/Application.php(386): yii\console\Application->handleRequest(Object(yii\console\Request))
#15 /home/dignity/yii(16): yii\base\Application->run()
#16 {main}
Нет возможности простым способом переопределить модели.
Единственный доступный способ без переписывания всего модуля целиком - переопределить глобально классы на уровне приложения. (Yii::$classMap)
Считаю, что было бы очень хорошо сделать переопределение моделей, таким же способом, как в расширении "dektrium/yii2-user".
Для чего нужно переопределение моделей - допустим, нам понадобится сохранять дополнительную информацию в придачу к IP. Например, UserAgent.
Мне понадобилось переопределять модели для встраивания UUID.
если вместо id например news_id как запускать?
если прописать вместо id ( 'target_id' => $model->news_id,) то будет ошибка такая:
Getting unknown property: app\models\News::id
Перенесу обсуждение сюда, т.к. есть что обмыслить...
Идею с js_before_vote и js_afrter_vote я понял.
Но основной вопрос остается открытым - как тут перехватить сообщения
и вывести их в плагине (например - noty)
Загвоздка в том, что в зависимости от результата действия, должен выводится соответствующий тип сообщения
$message = "Ваш голос учтен";
$type = "success";
или
$message = "Вы не авторизированы";
$type = "error";
<script type="text/javascript">
noty({
text: "' . $message . '",
type: "' . $type . '",
layout: "topRight",
timeout: 1500, // delay for closing event. Set false for sticky notifications
force: true
});
</script>
У себя я решал через виджет, обрабатывающий Flash сессию
#3 (comment)
Вывожу списком статьи через ListView.
Список кешируется. Кеш обновляется, если обновилась модель.
Голосование же идет по другому сценарию.
После факта голосования запись вставляется в таблицу rating.
Затем, после следующей выборки, обновляются поля в самой модели. Это если без кеша.
С кешем у меня эти поля не обновляются, т.к. не произошло обновления самой модели.
Получается, замкнутый круг: кеш не сбросился, т.к. не обновилась модель. Рейтинг не пересчитался, т.к. модель закеширована
Почему бы не объявлять массив моделей, т.к. они есть.
'modules' => [
'vote' => [
'matchingModels' => [ // matching model names with whatever unique integer ID
'common\models\Page' => 3, // or array with 'id' key
],
],
],
в виджете
<?php echo Display::widget([
'model_name' => $model::className(), // common\models\Page
//'model_name' => 'aphorism', // вместо такой записи
'target_id' => $model->id, // id of current element
]);
?>
поведение
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'class' => \chiliec\behaviors\RatingBehavior::className(),
'model_name' => self::className(), // common\models\Page
];
}
и тогда после вставки голоса в ratiing, имея готовый класс модели, запустить код, который находится в поведении RatingBehavior.
В таком случае, инвалидируется кеш, и список статей будет отображаться верно.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.