like, deslike - в товарах

F

Feetrus9836

Шопмейкер
#1
доброго времени суток
решил спросить, может кто уже такое делал
есть мысль сделать like deslike кнопки для товаров, которые ставятся при отправки отзыва, что бы был подсчет их и можно было вывести в категории в списке товаров
логика действий такая:
1. Человек делает отзыв стандартно при этом выбирает положительный отзыв (1) или негативный (0) (в базе будет поле в таблице oc_review, куда запишется 1 или 0)
2. На странице товаров просто будет выводится сколько положительных, а сколько отрицательных отзывов, и на странице категории тоже

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

для начала хочу так
в перспективе еще пересчитывать в процентном соотношении
 
Останнє редагування:
Симпатії: Baco
Baco

Baco

architect
#2
важкості для сайту я не бачу, тут чисто одне поле і в нього реалізувати запис TINYINT(1) значення, дає додатковий аргумент при сортуванні/фільтрації контенту/товарів по цьому параметру. але на мою думку, конструктивніше було б не просто лайк/дизлайк ставити, ащось накшталт розширеного відгуку, десь навіть бачив таку реалізацію, де по шкалі рейтингу навіть вказують швидкість доставки, якість спілкування, відповідність товару - макету на сайті. колись реалізовував лайкінг товарів (не відгуків) на сайті, по аякс, цікаво дивилось, але наразі прибрали, то ж приклад не покажу.
 
OP
F

Feetrus9836

Шопмейкер
Thread Starter #3
важкості для сайту я не бачу, тут чисто одне поле і в нього реалізувати запис TINYINT(1) значення, дає додатковий аргумент при сортуванні/фільтрації контенту/товарів по цьому параметру. але на мою думку, конструктивніше було б не просто лайк/дизлайк ставити, ащось накшталт розширеного відгуку, десь навіть бачив таку реалізацію, де по шкалі рейтингу навіть вказують швидкість доставки, якість спілкування, відповідність товару - макету на сайті. колись реалізовував лайкінг товарів (не відгуків) на сайті, по аякс, цікаво дивилось, але наразі прибрали, то ж приклад не покажу.
Спасибо за ответ
Здесь я хочу на брокарт сделать рейтинг сайт, своего рода сайт обзорник
По задумке в категории картинка объекта , название, количество положительных отзывов, количество отрицательных, и общее количество отзывов
Ну и на основании этого проводить фильтрацию объектов

С вёрсткой проблем нету, а вот с кодингом пока сижу разбираюсь
Спасибо за совет как лучше сделать
 
OP
F

Feetrus9836

Шопмейкер
Thread Starter #4
Ещё вопрос, как думаете может лучше сделать подсчет и запись в отдельное поле общей суммы лайков и дизлайков, что бы sql запрос со временем не стал тяжёлым ? Когда будет более 10 тыс отзывов
 
Baco

Baco

architect
#5
может лучше сделать подсчет и запись в отдельное поле общей суммы лайков и дизлайков
залежить від того, як ви збираєтесь групувати цю загальну цифру!
якщо просто по товарам, то не думаю що проблемно буде під кожен товар, витягувати загальну кількість:
SQL:
SELECT SUM(likes) FROM oc_reviews WHERE product_id = $my_product_id
ну а відповіді можна групувати в кеш файл, а то вже справа технічна, як згрупувати в кеш по категоріям чи виробникам, очищати при додаванні нового і т.д., тобто проблеми не бачу, головне щоб бізнес-логіка збільшувала конверсію!
 
OP
F

Feetrus9836

Шопмейкер
Thread Starter #7
Попробую что то сделать
Покажу потом результат

Это так хобби в свободное от фриланса время)
 
Симпатії: Baco
Baco

Baco

architect
#8
якщо цікавить якесь конкретне рішення і не проти його публічності, то пишіть, спробую прямо в цій темі розписати з практичної сторони рішення, я не люблю теорії, хоча іноді добре спроектоване рішення - дає швидкооптимізовану реалізацію в коді.
 
S

SlaSoft

Maestro
#10
Самый простой путь
два поля в товаре
dislike like
простой аяксовый запрос на инкремент/декремент
простой скрипт с защитой повторной отправки
 
OP
F

Feetrus9836

Шопмейкер
Thread Starter #11
Самый простой путь
два поля в товаре
dislike like
простой аяксовый запрос на инкремент/декремент
простой скрипт с защитой повторной отправки
наверное чуть неправильно объяснил я
человек оставляет отзыв - ставит положительный или отрицательный отзыв
у объекта к примеру 200 отзывов, нужно подсчитывать количество полож. и отриц. отзывов и записывать в общую информацию о товаре (дальше по всему сайту в товарах будут показыватся эти значения)
в категории сортировка у кого больше положительных отзывов по умолчанию
 
S

SlaSoft

Maestro
#12
не важно когда отправил

Важно поля в таблице product, чтобы не заниматься хней подсчета рейтинга

Это какой :censored: придумал это делать в getProducts
Создай поле рейтинга и меняй его при активации/деактивации отзыва..
МИНУС один подзапрос..
+ индексация по полю
+ сортировка быстрая
 
OP
F

Feetrus9836

Шопмейкер
Thread Starter #13
не важно когда отправил

Важно поля в таблице product, чтобы не заниматься хней подсчета рейтинга

Это какой :censored: придумал это делать в getProducts
Создай поле рейтинга и меняй его при активации/деактивации отзыва..
МИНУС один подзапрос..
+ индексация по полю
+ сортировка быстрая
пока это никто не придумал, так просто рассуждаем как лучше сделать) возможно кто то с этого форума поможет сделать не за просто так, надо только понять как будет правильнее при условии что в проекте будет более 1 тыс объектов и у каждого более 100 отзывов со временем
 
S

SlaSoft

Maestro
#14
пока это никто не придумал, так просто рассуждаем как лучше сделать)
Не понял
Я вам картинку показал с ликами дизлайками

Я не понимаю смысла в лайке/дизлайке при отзыве если есть рейтинг

лайкается/дизлайкается объект (товар, отзыв еще что-то)
 
OP
F

Feetrus9836

Шопмейкер
Thread Starter #15
Ну или как вариант
Есть же стандартный рейтинг на опенкарт
И можно прописать условие
Если оценки от 1 до 3 включительно - это дизлайк, если 4 или 5 это лайк
И тогда подсчитывать их
Получится что можно будет вывести количество хороших отзывов и количество плохих
 
Baco

Baco

architect
#16
простой скрипт с защитой повторной отправки
а ось тут детальніше, я довго міркував, як би захист від накручування зробити, окрім прописування "пряника" не знайшов оптимального рішення, а от при формуванні лайк/дизлайк при написанні відгуку, це можна зробити однократно, тут не бачу проблеми, ну я по правилам "нормалізації бази" я би все ж таки, як і рекомендує @SlaSoft створити окрему таблицю з ключиками на product_id та review_id, для швидкого отримання даних і 2-ва поля (+/-)
 
OP
F

Feetrus9836

Шопмейкер
Thread Starter #19
хотелось бы с помощью ваших советов прийти к какому то мнению, правильному
как организовать взаимосвязь в базе данных и отобразить все на сайте (с наименьшей нагрузкой для сайта)
при условии что будет много объектов и у каждого много отзывов
 
Baco

Baco

architect
#20
раз вже така петрушка, то давайте спілкуватись критеріями цифр, бо розуміння "багато" - досить відносне.
Щодо окремих поля для товару і його оновлення в процессі лайкінгу/диз, то слушне зауваження, та я чомусь звик кожну сутність в окрему таблицю пхати, з перспективою масштабування, хоча це властивість товару і може спокійнісінько бути в його таблиці, якщо брати контекст шановного ТС, то додавши поля до товару, ми втрачаємо ідентифікацію, з якого відгуку який рейтинг був висланий, якщо воно і не потрібно, важливим є лише момент 1/0 до товару в момент написання відгуку, то ось приблизний алгоритм реалізації:
0. в таблицю product нашої бази додати 2-ва поля, з типом таблиці int, та довжиною значень до 9, думаю мільярдні лайки хватить:
SQL:
ALTER TABLE `oc_product` ADD `likes` INT(9) NOT NULL DEFAULT '0' AFTER `viewed`;
ALTER TABLE `oc_product` ADD `dislikes` INT(9) NOT NULL DEFAULT '0' AFTER `likes`;
1. в самому контроллері товару додати публічний метод, котрий буде опрацьовувати прийнятий аргумент, та повертати відповідь/помилку:
PHP:
    public function addSympathy() {
        $this->load->language('product/product');

        $json = array();

        if ($this->request->server['REQUEST_METHOD'] == 'POST') {
         
            if (!isset($this->request->post['sympathy'])) {
                $json['error'] = $this->language->get('error_no_sympathy');
            }

            if (!isset($json['error'])) {
                $this->load->model('catalog/product');

                $callback = $this->model_catalog_review->addSympathy($this->request->get['product_id'], $this->request->post['sympathy']);
                if (!$callback) {
                    $json['success'] = $this->language->get('text_success');
                } else {
                    $json['error'] = $this->language->get('text_error_like');
                }            
            }
        }

        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }
2. в моделі товару, реалізувати аналогічний метод, для додавання інфи в базу по ключу product_id:
PHP:
    public function addSympathy($product_id, $sympathy = '') {
        if (empty($sympathy)) {
            return true;
        }
        if ($sympathy == '0') {
            $this->db->query("UPDATE " . DB_PREFIX . "product SET dislikes = (dislikes + 1) WHERE product_id = '" . (int)$product_id . "'");
        } elseif ($sympathy == '1') {
            $this->db->query("UPDATE " . DB_PREFIX . "product SET likes = (likes + 1) WHERE product_id = '" . (int)$product_id . "'");
        }
        return false;
    }
3. для вьюшки (tpl/twig) я б накидав приблизно ось такий скрипт (якщо користуєшся twig, то {{ product_id }}, якщо tpl, то <?php echo $product_id; ?>):
JavaScript:
function addSympaty(like) {
    $.ajax({
        url: 'index.php?route=product/product/addSympathy&product_id={{ product_id }}',
        type: 'post',
        dataType: 'json',
        data: 'sympathy=' + (typeof(like) != 'undefined' ? like : 0),
        beforeSend: function() {
            $('#button-like').button('loading');
        },
        complete: function() {
            $('#button-like').button('reset');
        },
        success: function(json) {
            $('.alert-dismissible').remove();
            if (json['error']) {
                $('#review').after('<div class="alert alert-danger alert-dismissible"><i class="fa fa-exclamation-circle"></i> ' + json['error'] + '</div>');
            }
            if (json['success']) {
                $('#review').after('<div class="alert alert-success alert-dismissible"><i class="fa fa-check-circle"></i> ' + json['success'] + '</div>');
            }
        }
    });
}
4. додати в мовні файли локалізації товару 2-ві змінні типу:
PHP:
$_['error_no_sympathy']        = 'Помилка відправки симпатії, оновіть сторінку!';
$_['text_error_like']         = 'Симпатія не врахована, спробуйте ще раз!';
$_['text_success_like']     = 'Дякуємо за Ваше вподобання, приємних покупок!';
5. навісити на кнопочки лайкінгу відповідні евенти:
для дизлайку: addSympaty(0)
для лайку: addSympaty(1)
перевірку на наявність пряника чи локального сховища вважаю непотрібною, оскільки метод лайкінку напряму зав'язаний на відправці рейтингу.
 
Останнє редагування:
OP
F

Feetrus9836

Шопмейкер
Thread Starter #21
получается нет возможности в случае ошибки клиента менять значения администратору?
или если добавить еще поля в таблицу oc_review что бы кроме рейтинга еще и туда добавлялись значения?
 
Останнє редагування:
OP
F

Feetrus9836

Шопмейкер
Thread Starter #22
к примеру, будет в дальнейшем массовая заливка объектов и отзывов к ним, в этом случае если я правильно понял, то подсчета значений положительных и отрицательных для объекта не будет?
 
Baco

Baco

architect
#23
получается нет возможности в случае ошибки клиента менять значения администратору?
в адмінці інтерфейс не створював, то вже технічний момент, в картці товару повиводити для редагування то не складно.
или если добавить еще поля в таблицу oc_review что бы кроме рейтинга еще и туда добавлялись значения?
тоді прив'язка йде до рейтингу, ане до товару. тут вже з оптимізацією визначитись треба, що оптимальніше і для чого то треба.
подсчета значений положительных и отрицательных для объекта не будет?
якщо в таблиці значення будуть, то повиводити їх потім у потрібному місці - то кілька методів у потрібному місці і готово.
ви досить абстрактно все описуєте, напишіть конкретні цифри, чи змоделюйте ситуацію, щоб розуміти, про що мова.
 
OP
F

Feetrus9836

Шопмейкер
Thread Starter #24
для юзера:
оставлять отзыв с - имя, отзыв, оценка от 1 до 10, лайк или дизлайк (как на скрине выше)
для админа:
менять отзыв, оценку, лайк или дизлайк

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

подсчет не должен быть тяжелым при выводе контента на страницу товара или в категории (поэтому думаю что тут лучше показывать уже готовые значение из таблицы)
к примеру если в категории 50 объектов и у каждого объекта по 200 отзывов
 
Marius

Marius

Шопмейкер
#25
Если создать поля в таблицу `oc_review`, то мы имеем большую продуктивность и выбираем данные совместно с рейтингом, по требованию заказчика, это оптимальный вариант проектирования БД.
Выборку делать отдельным методом в модели отзывов: catalog/model/catalog/review.php по ID товара примерно так:
PHP:
    public function getAvgSympathyByProductId($product_id) {
       
        $raiting = $this->cache->get('review.raiting');
       
        if (!isset($raiting[$product_id])) {
           
            $query = $this->db->query("SELECT AVG(r.rating) AS summary, SUM(r.likes) AS like, SUM(r.dislikes) AS dislike FROM " . DB_PREFIX . "review r LEFT JOIN " . DB_PREFIX . "product p ON (r.product_id = p.product_id) WHERE p.product_id = '" . (int)$product_id . "' AND p.date_available <= NOW() AND p.status = '1' AND r.status = '1' ORDER BY r.date_added DESC");          
           
            $raiting[$product_id] = $query->num_rows ? $query->row : false;

            $this->cache->set('review.raiting', $raiting);
        }

        return $query->rows;
    }
В итоге, получаем массив, в котором имеем 3 свойства товара (рейтинг - среднее значение, количество лайков и количество дизлайков), сразу добавил систему кэширования, для исключения повторного запроса к базе.
 
Симпатії: Baco
Зверху