yii2-vote icon indicating copy to clipboard operation
yii2-vote copied to clipboard

Обновить модель после голосования

Open loveorigami opened this issue 9 years ago • 19 comments

Вывожу списком статьи через 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.

В таком случае, инвалидируется кеш, и список статей будет отображаться верно.

loveorigami avatar Jan 17 '16 16:01 loveorigami

единственное, что заметил, это Post-ом шлется название модели без слешей, как commonmodelsPage Тогда в проверках нужно вырезать слеши в matchingModels, а при совпадении вернуть правильную модель

loveorigami avatar Jan 17 '16 16:01 loveorigami

Идея замечательная, но нужно всё хорошенько обдумать перед таким крутым изменением. Наверняка найдутся ещё какие-то подводные камни.

chiliec avatar Jan 18 '16 10:01 chiliec

Вот, немного похожее решение того, о чем я написал выше и в след. issue. https://github.com/AkiraShirase/yii2-vote

loveorigami avatar Jan 18 '16 11:01 loveorigami

Ну, тут особо кардинального изменения не произошло )... было - page, стало - common\models\Page. В предлагаемом выше модуле модель передается через crc32 https://github.com/AkiraShirase/yii2-vote/blob/master/widgets/Vote.php#L46 Единственное, что - после сохранения модели rating, выполнить метод afterFind поведения с привязкой к передаваемой модели..

В принципе - можно сделать отдельную ветку и там все это потестить).

loveorigami avatar Jan 18 '16 11:01 loveorigami

В принципе и от настройки matchingModels тогда можно отказаться, если создать ещё одну табличку с PK и model_name и связать её с rating. Тогда вообще всё магически будет происходить. Правда существующим пользователям придётся в неё залезть чтобы настроить такие же соответствия, какие сейчас прописаны в конфиге...

chiliec avatar Jan 18 '16 15:01 chiliec

Можно сделать, как один из вариантов... Во многих проектах такая табличка уже есть (у меня , по крайней мере), при привязке комментариев, избранного, и тп...

Также, такой подход удобен для выборки в личном кабинете всех проголосованных записей (типа - избранного)

loveorigami avatar Jan 18 '16 15:01 loveorigami

Правда, если убирать эту настройку, надо придумать как оставить возможность задавать собственные значения для разрешения голосовать гостям и менять свой голос. Или эта фича не нужна и глобальных значений достаточно?

chiliec avatar Jan 21 '16 07:01 chiliec

Я не призывал убирать эту настройку )... Как по мне - она вполне логична и видно, к какой модели применяется голосование и с какими настройками. Вариант в конфиге с привязкой к namespace модели намного понятнее и удобнее (знаешь, где искать)

    'modules' => [
        'vote' => [
            'matchingModels' => [ // matching model names with whatever unique integer ID
                'common\models\Page' => 3,
                'my-local-module\models\Page' => ['id'=>2, 'allow_guests'=>false],
                'vendor\chiliec\module\page\models\Page' => ['id'=>4, 'allow_guests'=>true],
            ],
        ],
    ],

намного понятнее, чем

    'modules' => [
        'vote' => [
            'matchingModels' => [ // matching model names with whatever unique integer ID
                'page1' => 3,
                'page2' => ['id'=>2, 'allow_guests'=>false],
                'page3' => ['id'=>4, 'allow_guests'=>true],
            ],
        ],
    ],

loveorigami avatar Jan 21 '16 07:01 loveorigami

Переделал name => id на id => name в конфиге, что, как мне кажется, более логично (индексы массива). Изменения в ветке develop, я поправил документацию, можете попробовать. Теперь можно предположить, что у нас есть имя модели и можно подумать над тем, как сбросить её кэш...

chiliec avatar Jan 24 '16 15:01 chiliec

посмотрел, толковое решение... Ну раз начали переделывать ))), то можно еще в виджете вместо названия модели передать саму модель,

        'model' => $model, //*Obligatory parameter. Object for Like/Dislike.
        'primaryField' => 'id', //Name of primary key for model

а затем, после сохранения голоса, например тут https://github.com/Chiliec/yii2-vote/blob/master/actions/VoteAction.php#L77

запустить метод записи в модель, аналогичный https://github.com/Chiliec/yii2-vote/blob/master/behaviors/RatingBehavior.php#L38

типа

$model::afterFind();

И поскольку обновится запись, кеш у меня автоматически сбросится...

loveorigami avatar Jan 30 '16 09:01 loveorigami

Я вот всё думаю как бы поменьше действий делать для подключения. Подключение поведения уже происходит динамически, теперь хочется ещё вынести рейтинг во внешнюю таблицу. Хотелось бы формировать его на лету (ведь по сути это всё вычисляемые избыточные данные), но похоже не получится, ведь необходимо оставить возможность делать выборку с учетом рейтинга. Надо ещё подумать, возможно найдется какой-то вариант. Кстати, а как у Вас кэширование происходит?

chiliec avatar Jan 30 '16 13:01 chiliec

За кеширование у меня отвечает тоже поведение. Кеш сбрасывается по времени, или если модель обновилась.

Примерно, как тут https://github.com/trntv/yii2-starter-kit/blob/master/common/behaviors/CacheInvalidateBehavior.php

loveorigami avatar Jan 30 '16 16:01 loveorigami

Выборку с учетом рейтинга делать надо ). У меня сортировка ListView содержит параметр "по рейтингу". А еще понадобится выборка в личном кабинете всех записей, за которые отдан голос или добавленных в избранное.

Насчет подключения - тоже не очевидно. Можно оставить как вариант через bootstrap.

Так получается, что поведение будет цепляться к каждой модели и перебирать массив моделей из конфига... А на самом деле в проекте у меня поведение нужно в 4-5 моделях из более чем 40.

Тем более, что есть уже четкие сформировавшиеся методики подключения поведений. Если я его подключил к определенной модели, то я знаю, что это поведение делает... И в случае чего могу отключить (или заменить на другое)...

К примеру, давно хотел предложить (или сделать у себя) добавить возможность добавлять в избранное. Это тоже своего рода "голосование". Просто удобно одним виджетом вывести эти три кнопки. У себя еще на CodeIgniter я делал такой модуль http://new.loveorigami.info/world

loveorigami avatar Jan 30 '16 16:01 loveorigami

Возможность выборки с учетом рейтинга - обязательное условие, без которого и нет смысла выносить рейтинг во внешнюю таблицу. Главное теперь понять как это сделать :neckbeard:

Естественно можно подключать и по-старинке вместо bootstrap, но так удобнее - меньше действий и можно быть уверенным, что у всех перечисленных моделей есть это поведение. И пусть оно во всех 40 моделях будет, раз уж они поддерживают голосование, оверхэд минимален.

Насчет избранного надо подумать, возможно отдельный issue создать, пока в концепции данного модуля применения не особо вижу, всё же это несколько иная функциональность.

chiliec avatar Jan 31 '16 12:01 chiliec

Насчет избранного надо подумать, возможно отдельный issue создать, пока в концепции данного модуля применения не особо вижу, всё же это несколько иная функциональность.

открыл issue #19 под избранное.

Там я описал функциональность - все аналогично и проще - по крайней мере я у себя так делал. А вот когда голосуешь, всегда есть желание понравившуюся запись иметь у себя в закладках (избранном)...

loveorigami avatar Jan 31 '16 14:01 loveorigami

Примерно, как тут https://github.com/trntv/yii2-starter-kit/blob/master/common/behaviors/CacheInvalidateBehavior.php

Ну тогда мне кажется можно добавить вот это:

$modelName = static::getModelNameById($modelId);
$model = $modelName::findOne($targetId);
$model->trigger($modelName::EVENT_AFTER_UPDATE);

после этой строчки https://github.com/Chiliec/yii2-vote/blob/develop/models/Rating.php#L189 Ну или что-нибудь вроде того. Можете PR сделать если сработает.

chiliec avatar Feb 06 '16 18:02 chiliec

пока не делаю, т.к. отключил кеширование при разработке и тестировании этого модуля. При кешировании, если помните, у меня не подгружается js. Так что сам action не будет срабатывать.

Если получится нам переделать через asset - тогда буду пробовать

loveorigami avatar Feb 07 '16 12:02 loveorigami

Если получится нам переделать через asset

Очень не хочется отказываться от переопределения методов, выполняющихся после голосования. Но, возможно, это можно сделать не из PHP, формируя js-код, а перегружая их прямо в Javascript в другом месте. Это бы решило проблему #18.

chiliec avatar Feb 08 '16 12:02 chiliec

Я на днях тут делал PR в ajax-modal https://github.com/karnbrockgmbh/yii2-modal-ajax/blob/master/README.md

Так вот, там скрипт написан в виде плагина, с возможностью call-back- ов, который можно написать прямо на странице в виде

$('.voted').on('kbModalShow', function(event, data, status, xhr) {
    console.log('kbModalShow');
});

Реализуются они при помощи триггеров https://github.com/karnbrockgmbh/yii2-modal-ajax/blob/master/assets/js/kb-modal-ajax.js#L54

loveorigami avatar Feb 09 '16 06:02 loveorigami