Русское сообщество fluxbb

Быстрый лёгкий надёжный форумный движок

Вы не вошли.

Объявление

Вы можете внести свой вклад в содержание сайта. Жертвователи попадут в почетную группу "Спонсоры". Поддержать сайт.

#1 2016-11-28 20:09:58

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 887
Сайт

[MOD] Like (similar to Facebook)

Собираюсь написать систему лайков для форума, которая была бы подобна фейсбуковской. А то хочется поблагодарить Висмана, а простой и удобной кнопки нет smile

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

Feature list:
  • если ты зарегистрирован, можешь лайкнуть сообщение,

  • можешь передумать и убрать свой лайк,

  • все видят сколько лайков набрало сообщение,

  • ты видишь лайкал ли ты сам это сообщение

  • graceful degradation, если JS вдруг недоступен, кнопка всё равно должна работать, пусть с перегрузкой страницы.

Как это мне видится на уровне таблиц БД.

В posts добавить колонку num_likes с числом лайков. Это позволит без джойнов выводить цифры в ленте сообщений.
Отдельная таблица post_likes с уникальным составным ключём (user_id, post_id) чтобы определять голосовал ли пользователь за сообщение.

Думается мне, что "лайкать" будут часто, а "разлакивать" очень редко. Поэтому слегка оптимизирую наиболее частый кейс. Не буду делать предварительный select чтобы узнать лайкал ли уже пользователь это сообщение. База сама подскажет через возвращаемое число добавленных записей.

$db->query("INSERT IGNORE INTO post_likes(user_id, post_id, created_on) VALUES($uid, $pid, $now)");
if ($db->affected_rows()) {
    // Yes, I like it
    $db->query("UPDATE posts SET num_likes = num_likes + 1 WHERE id = $pid");
} else {
    // No, I changed my mind
    $db->query("UPDATE posts SET num_likes = num_likes - 1 WHERE id = $pid");
    $db->query("DELETE FROM post_likes WHERE user_id = $uid AND post_id = $pid");
}

Продолжение следует…


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

  • Нравится: 3

#2 2016-11-28 20:17:29

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 887
Сайт

Re: [MOD] Like (similar to Facebook)

Итак, для вывода количества лайков в каждом сообщении нам не надо добавлять джойны. Достаточно впилить одну колонку в таблицу posts. Но выше я включил фичу, что пользователь будет видеть статус лайкал ли он сам конкретное сообщение. То есть нам таки понадобится обращение к post_likes при выводе ленты.

Я думаю можно это сделать один раз, когда у нас будет накоплен список сообщений на странице. Причем только в случае если пользователь не Guest.

$pids = implode(',', $post_ids);
$result = $db->query("SELECT post_id FROM post_likes WHERE user_id = $uid AND post_id IN($pids)");

Итоговый список будем использовать для добавления класса active в кнопки Like.


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

  • Нравится: 1

#3 2017-01-08 16:10:02

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 887
Сайт

Re: [MOD] Like (similar to Facebook)

Применил мод к нашему форуму. Если вы зарегистрированный пользователь, обратите внимание на строку под каждым сообщением. Там должна появиться ссылка "Понравилось"/"Разонравилось".

Лайкайте!!! Задавайте вопросы, предлагайте улучшения (я всё равно сделаю по своему).


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

  • Нравится: 2

#4 2017-01-08 16:30:13

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,236
Сайт

Re: [MOD] Like (similar to Facebook)

@artoodetoo, счас народ красивостей просить будет smile

Offline

#5 2017-01-08 18:01:04

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 887
Сайт

Re: [MOD] Like (similar to Facebook)

Не знаю когда соберусь с силами чтобы оформить мод как принято. Пока некогда.
Как есть скачать можно отсюда (пробелы уберите):

https: // dl.dropboxusercontent.com/u/11837706/flux-likes-20160108.zip
https : //www.dropbox.com/s/2022e93oux82nes/flux-likes-20160108.zip?dl=0

во viewtopic все изменения можно найти diff-ом либо посиком подстроки "vote"
в стили добавил только один селектор .postnumvotes


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

  • Нравится: 1

#6 2017-01-09 16:02:44

Aлександр
Участник
Зарегистрирован: 2016-08-12
Сообщений: 70

Re: [MOD] Like (similar to Facebook)

artoodetoo пишет:

Не знаю когда соберусь с силами чтобы оформить мод как принято. Пока некогда.
Как есть скачать можно отсюда (пробелы уберите):

https: // dl.dropboxusercontent.com/u/11837706/flux-likes-20160108.zip

во viewtopic все изменения можно найти diff-ом либо посиком подстроки "vote"
в стили добавил только один селектор .postnumvotes

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

Вообще уже есть где фантазию проявить
По аналогии можно сделать дизлайк и посты при множестве дизлайков будут помечены как спам или по крону будут удаляться...

Offline

#7 2017-01-09 16:38:46

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,236
Сайт

Re: [MOD] Like (similar to Facebook)

По аналогии можно сделать дизлайк и....

И тут начинается война wink

Offline

  • Нравится: 3

#8 2017-01-10 01:14:38

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 887
Сайт

Re: [MOD] Like (similar to Facebook)

Добавил csrf_token и иконку.
Думаю как бы органично впилить лайки в поиск и пользовательский профиль.


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

  • Нравится: 1

#9 2017-01-11 02:18:52

Aлександр
Участник
Зарегистрирован: 2016-08-12
Сообщений: 70

Re: [MOD] Like (similar to Facebook)

artoodetoo пишет:

Добавил csrf_token и иконку.
Думаю как бы органично впилить лайки в поиск и пользовательский профиль.

Может сделать опцию возможности ставить лайки только на тему, для первого поста?

$voted = array_search($cur_post['id'], $voted_ids) !== false;
if (!empty($cur_post['num_votes']) && $pun_config['o_postlike'] == '1' &&  $cur_topic['first_post_id']  {
if ($voted)
$post_actions[] = '<li class="postnumvotes">'.sprintf($lang_vote['Num Votes w. You'], $cur_post['num_votes']).'</li>';
else
$post_actions[] = '<li class="postnumvotes">'.sprintf($lang_vote['Num Votes'], $cur_post['num_votes']).'</li>';
}
else if($pun_config['o_postlike'] == '2' && !empty($cur_post['num_votes'])) {
if ($voted)
$post_actions[] = '<li class="postnumvotes">'.sprintf($lang_vote['Num Votes w. You'], $cur_post['num_votes']).'</li>';
else
$post_actions[] = '<li class="postnumvotes">'.sprintf($lang_vote['Num Votes'], $cur_post['num_votes']).'</li>';
}

Offline

  • Нравится: 1

#10 2017-01-11 10:21:23

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 887
Сайт

Re: [MOD] Like (similar to Facebook)

Может сделать опцию возможности ставить лайки только на тему, для первого поста?

Да, в этом есть смысл.

Есть такая идея: считать лайк первого сообщения особым образом — лайкать саму тему. Как на StackOverflow: есть баллы за вопросы и есть баллы за ответы. Если сделать так, то можно будет сортировать темы по лайкам.


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

#11 2017-04-03 16:49:54

wwput
Участник
Зарегистрирован: 2011-03-06
Сообщений: 31

Re: [MOD] Like (similar to Facebook)

@artoodetoo,
По ссылке https: //dl.dropboxusercontent.com/u/11837706/flux-likes-20160108.zip файла больше нет.
Если не сложно, перезалейте пожалуйста.

2017-04-15 18:18:31 artoodetoo пишет:

я делал ссылку некликабельной. наверное есть причины :) не надо это "исправлять" пожалуйста

Offline

#12 2017-04-15 18:19:08

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 887
Сайт

Re: [MOD] Like (similar to Facebook)

https: //www.dropbox.com/s/2022e93oux82nes/flux-likes-20160108.zip?dl=0


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

#13 2017-04-16 22:46:04

wwput
Участник
Зарегистрирован: 2011-03-06
Сообщений: 31

Re: [MOD] Like (similar to Facebook)

спасибо

Offline

#14 2017-06-12 13:53:32

serpech
Новичок
Зарегистрирован: 2017-06-12
Сообщений: 8

Re: [MOD] Like (similar to Facebook)

При переходе в темы получаю такую неприятность

File: \viewtopic.php
Line: 232

FluxBB reported: Unable to fetch vote info 

Database reported: Table 'fbb.post_votes' doesn't exist (Errno: 1146)

Догадываюсь что нужно создать таблицу.Как правильно это сделать?

Offline

#15 2017-06-12 16:03:32

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,236
Сайт

Re: [MOD] Like (similar to Facebook)

@serpech, видимо такая табличка нужна

 CREATE TABLE `fx15_post_votes` (
   `post_id` int(10) unsigned NOT NULL DEFAULT '0',
   `user_id` int(10) unsigned NOT NULL DEFAULT '0',
   `voted` int(10) unsigned NOT NULL DEFAULT '0',
   PRIMARY KEY (`user_id`, `post_id`)
 );

 ALTER TABLE `prefix_posts` 
 ADD COLUMN `num_votes` mediumint(8) unsigned NOT NULL DEFAULT '0';

Вместо fx15_ и prefix_ нужно подставить префикс своих таблиц и выполнить оба запроса в phpMyAdmin на базе форума.

Offline

  • Нравится: 2

#16 2017-06-12 17:52:06

serpech
Новичок
Зарегистрирован: 2017-06-12
Сообщений: 8

Re: [MOD] Like (similar to Facebook)

Спасибо!Работает прекрасно.

Offline

#17 2020-02-10 17:41:23

Aлександр
Участник
Зарегистрирован: 2016-08-12
Сообщений: 70

Re: [MOD] Like (similar to Facebook)

Visman пишет:

@serpech, видимо такая табличка нужна
...

А подскажите на счет вашей сборки viewtopic.php как поправить?

Понятно что этот блок:

$voted = array_search($cur_post['id'], $voted_ids) !== false;
	if (!empty($cur_post['num_votes'])) {
		if ($voted)
			$post_actions[] = '<li class="postnumvotes">'.sprintf($lang_vote['Num Votes w. You'], $cur_post['num_votes']).'</li>';
		else
			$post_actions[] = '<li class="postnumvotes">'.sprintf($lang_vote['Num Votes'], $cur_post['num_votes']).'</li>';
	}
	if (!$pun_user['is_guest']) {
		if ($voted)
			$post_actions[] = '<li class="postvote"><span><a href="vote.php?pid='.$cur_post['id'].'">'.$lang_vote['Vote Down'].'</a></span></li>';
		else
			$post_actions[] = '<li class="postvote"><span><a href="vote.php?pid='.$cur_post['id'].'">'.$lang_vote['Vote Up'].'</a></span></li>';
	}

и этого блока

if (empty($post_ids))
	error('The post table and topic table seem to be out of sync!', __FILE__, __LINE__);


// Добавить после
 
// Retrieve the post voted by user 
$voted_ids = array();
if (!$pun_user['is_guest'])
{
	$result = $db->query('SELECT pv.post_id FROM '.$db->prefix.'post_votes AS pv WHERE pv.user_id='.$pun_user['id'].' AND pv.post_id IN ('.implode(',', $post_ids).')', true) or error('Unable to fetch vote info', __FILE__, __LINE__, $db->error());
	while ($row = $db->fetch_assoc($result))
		$voted_ids[] = $row['post_id'];
}

Ланг файлы подключаем в последний момент

// Load the viewtopic.php language file
require PUN_ROOT.'lang/'.$pun_user['language'].'/topic.php';
//require PUN_ROOT.'lang/'.$pun_user['language'].'/vote.php';

я так понял нужен ещё

$result = $db->query( .. p.num_votes

Редактировался Aлександр (2020-02-10 17:46:30)

Offline

#18 2020-02-10 18:31:46

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,236
Сайт

Re: [MOD] Like (similar to Facebook)

@Aлександр, если вопрос ко мне, то надо сначала @artoodetoo растрясти на полный код, который на этом сайте стоит, а то у меня его нет в наличии, на гитхабе тоже не нашел. Ссылки на дропбокс устаревшие.

Offline

#19 2020-02-10 18:58:30

Aлександр
Участник
Зарегистрирован: 2016-08-12
Сообщений: 70

Re: [MOD] Like (similar to Facebook)

Visman пишет:

@Aлександр, Ссылки на дропбокс устаревшие.

https://www.dropbox.com/s/2022e93oux82n … 8.zip?dl=0

Рабочие

Offline

#20 2020-02-10 19:09:39

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,236
Сайт

Re: [MOD] Like (similar to Facebook)

@Aлександр, посмотрю сейчас и отпишусь чуть позже.

Offline

  • Нравится: 1

#21 2020-02-10 19:35:57

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,236
Сайт

Re: [MOD] Like (similar to Facebook)

@Aлександр, примерно, что надо:
1. Выполнить запросы http://fluxbb.qb7.ru/forum/viewtopic.ph … 077#p30077

Для файла viewtopic.php
2. после

require PUN_ROOT.'lang/'.$pun_user['language'].'/topic.php';

добавить

require PUN_ROOT.'lang/'.$pun_user['language'].'/vote.php';

3. после

// Poll MOD - Visman
if (in_array($cur_topic['first_post_id'], $post_ids))
	poll_display_topic($id, $pun_user['id'], $p, true);
// Poll MOD - Visman

добавить

// Retrieve the post voted by user
$voted_ids = array();
if (!$pun_user['is_guest'])
{
	$result = $db->query('SELECT pv.post_id FROM '.$db->prefix.'post_votes AS pv WHERE pv.user_id='.$pun_user['id'].' AND pv.post_id IN ('.implode(',', $post_ids).')', true) or error('Unable to fetch vote info', __FILE__, __LINE__, $db->error());
	while ($row = $db->fetch_assoc($result))
		$voted_ids[] = $row['post_id'];
}

4. в этот запрос

$result = $db->query('SELECT u.warning_all, u.gender, u.email, u.title, u.url, u.location, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.messages_enable, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, p.edit_post, p.user_agent, g.g_id, g.g_user_title, g.g_promote_next_group, g.g_pm FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE p.id IN ('.implode(',', $post_ids).') ORDER BY p.id', true) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());

добавить поле

, p.num_votes

5. перед

	// Perform the main parsing of the message (BBCode, smilies, censor words etc)

добавить

	$voted = array_search($cur_post['id'], $voted_ids) !== false;
	if (!empty($cur_post['num_votes'])) {
		if ($voted)
			$post_actions[] = '<li class="postnumvotes">'.sprintf($lang_vote['Num Votes w. You'], $cur_post['num_votes']).'</li>';
		else
			$post_actions[] = '<li class="postnumvotes">'.sprintf($lang_vote['Num Votes'], $cur_post['num_votes']).'</li>';
	}
	if (!$pun_user['is_guest']) {
		if ($voted)
			$post_actions[] = '<li class="postvote"><span><a href="vote.php?pid='.$cur_post['id'].'&amp;csrf_hash='.csrf_hash('vote'.$cur_post['id']).'">'.$lang_vote['Vote Down'].'</a></span></li>';
		else
			$post_actions[] = '<li class="postvote"><span><a href="vote.php?pid='.$cur_post['id'].'&amp;csrf_hash='.csrf_hash('vote'.$cur_post['id']).'">'.$lang_vote['Vote Up'].'</a></span></li>';
	}

Для файла vote.php
6. После

$pid = isset($_GET['pid']) ? intval($_GET['pid']) : 0;

добавить

confirm_referrer('vote'.$pid);

В 5 и 6 шаге добавлен csrf_hash для исклюения накрутки или скрутки голосов. + не даст проголосовать за недоступные посты.
Код не проверен.

Offline

#22 2020-02-10 19:41:13

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,236
Сайт

Re: [MOD] Like (similar to Facebook)

И возможно лучше

$voted_ids[] = $row['post_id'];

заменить на

$voted_ids[$row['post_id']] = $row['post_id'];

а условие

$voted = array_search($cur_post['id'], $voted_ids) !== false;

на

$voted = isset($voted_ids[$cur_post['id']]);

Offline

#23 2020-02-10 20:14:23

Aлександр
Участник
Зарегистрирован: 2016-08-12
Сообщений: 70

Re: [MOD] Like (similar to Facebook)

В принципе я 1 в 1 всё это делал
и получаю ошибку

File: /viewtopic.php
Line: 368

FluxBB reported: Unable to fetch post info

Database reported: Unknown column 'p.num_votes' in 'field list' (Errno: 1054) 
$result = $db->query('SELECT u.warning_all, u.gender, u.email, u.title, u.url, u.location, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.messages_enable, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, p.edit_post, p.user_agent, g.g_id, g.g_user_title, g.g_promote_next_group, g.g_pm, p.num_votes FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE p.id IN ('.implode(',', $post_ids).') ORDER BY p.id', true) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());

естественно таблицу post_votes (без префикса)  создал и добавил в posts колонку num_votes

 CREATE TABLE `post_votes` (
   `post_id` int(10) unsigned NOT NULL DEFAULT '0',
   `user_id` int(10) unsigned NOT NULL DEFAULT '0',
   `voted` int(10) unsigned NOT NULL DEFAULT '0',
   PRIMARY KEY (`user_id`, `post_id`)
 );

 ALTER TABLE `posts` 
 ADD COLUMN `num_votes` mediumint(8) unsigned NOT NULL DEFAULT '0';

Редактировался Aлександр (2020-02-10 20:17:51)

Offline

#24 2020-02-10 20:17:53

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,236
Сайт

Re: [MOD] Like (similar to Facebook)

@Aлександр, добавьте поле num_votes в таблицу posts тогда не запросом, а через phpMyAdmin, через редактирование структуры таблицы.

Offline

#25 2020-02-10 20:35:29

Aлександр
Участник
Зарегистрирован: 2016-08-12
Сообщений: 70

Re: [MOD] Like (similar to Facebook)

я всё правильно сделал проблему кажется понял ))))
я создал таблицу posts и всё не мог понять почему мне пишет эту ошибку ведь я всё сделал правильно и ошибка понятная. Но как оказалось я думал что fluxbbposts это цельная таблица самого движка (просто давно не работал с форумом) а это блин префикс fluxbb а когда делал запросы не обратил на это внимание, тупо смотрел в таблицу posts не замечая что она к форуму не относиться

Редактировался Aлександр (2020-02-10 20:37:09)

Offline

Подвал доски

Под управлением FluxBB. Хостинг Hostens