Нужно реализовать голосование к каждому материалу на сайте (понравилось/не понравилось, а-ля пальцы вверх-вниз на youtube). Реализовал следующим образом: в таблице, где собственно хранятся статьи, добавил два поля, like и dislike. По клику на нужный div идет аяксом запрос на пхп-обработчик, который открывает базу, проверяет сколько там уже лайков (дислайков), добавляет ещё один, записывает то что получилось и возвращает то, что получилось, вызывавшему скрипту.
Теперь осталось только придумать, как запретить голосовать дважды. Есть идея записывать айпишники, и при загрузке страницы проверять, голосовал такой или нет, и если да — обзывать нужный div по-другому, чтобы кнопка была неактивна.
Вопрос — где хранить айпишники? В базу не получится, для каждой статьи ведь должен быть отдельный список
Если два вас накрутка не критична, то лучший вариант куки/локалсторейдж и т.д., в общем вынести это в клиента.
Если критично, то сделайте простую табличку с двумя полями айпи(любой другой идентификатор) и айди новости. Сделайте уникальный индекс из этих двух полей. Простым джоином, при получение данных о новости вы узнаете голосовал уже этот клиент или нет, а от повторного голосования без перезагрузки спасет индекс, и не надо самому проверять.
И не надо пхп обработчику проверять что там в базе при лайке, пусть это сама база делает. Посылайте просто инкримент или декримент, и в ответ запрашивайте уже что там получилось.
Ну и по окончании какого-то периода лайки можно отключать, а табличку чистить. Можно избавиться и от хранения цифр в самой новости, а просто считать суммы по табличке логов +), но все зависит от вашего объема данных.
На 1 IP могут быть десятки. сотни, тысячи пользователей. Например, у Гугл есть специальный алгоритм определения числа пользователей за IP. Можете погуглить PDF.
Но в вашем случае, это излишне сложно — хватит ограничения на 1 голос с IP.
Хранить — сделайте таблицу вида user_ip INTEGER(...), article_id, vote. Такая таблица, в случае правильнйо расстановки индексов, работает быстро и легко кешируется в случае надобности.
Надеюсь, фраза "пхп-обработчик, который открывает базу, проверяет сколько там уже лайков (дислайков), добавляет ещё один, записывает то что получилось и возвращает то, что получилось, вызывавшему скрипту" не означает что-то типа такого (псевдокод)
counter = sql("select like_count from table where ...");
counter += 1
sql("update table set like_count="+counter+"where ...");
return counter;
Я не понял, что мешает сделать таблицу в базе
create table Votes (
article_id integer not null,
vote_ip integer not null,
vote_value tinyint not null,
PRIMARY KEY(article_id, vote_ip)
)
?
Ну, базы данных нужны именно для хранения данных.
Надо просто создать отдельную табличку, как советовали ранее.
А как отличать пользователей — эта задача стара, как интернет.
Можно ставить куки. А в дополнение к кукам запрещать голосовать ip-адресам, которые голосовали достаточно недавно (полчаса, час, полдня — решать вам).
То есть, таблица со списком ip и временем голосования.
Сейчас модно делать всякие интеграции с соц. сервисами.
Почему бы не сделать голосование, построенное на соц сетях, что-то типа thebattleofbrands.com/ru?
И в базе хранить уже сумму счетчиков по каждой из соц сетей.
Если у вас анонимусы голосуют — сильно не защититесь. Но если очень надо, то в базу писать как раз получится, потому что главный вопрос — не где хранить, а как быстрее достать, и лучше базы здесь только key-value (mongodb например). Впрочем, вряд ли вы будете эти логи хранить месяцами. Впоследствие, голосование будете прекращать через месяц, так что база пойдет.
А вот ждать ответа от AJAX чтобы пересчитать на страничке рейтинг — это странно. В JS есть плюсование и деление ;)
При голосовании проверяйте наличие записи с соответствующими userId и articleId. Если запись есть — уже голосовали, грозим юзеру пальцем. Записи нет — добавляем её, указывая в поле vote -1 если голосовали против, +1 — если за.
Как бонус — поля like и dislike больше не нужны, оценку статьи можно узнать простым SELECT-ом.
А джоины пробовали?
Попробуйте себе сделать табличку: ид + ип + юзер_ид, да потом запрещать голосовать вторично для каждого юзера, запрет голосования людей без юзер_ид до определенного количества и в сессии держать голоса для.
таблицы таблицами, но нельзя забывать про время когда проголосовали. Это будет полезно, чтобы не засирать всю таблицу миллионами записей. Например, можно удалять айпишники которые прогосовали более двух недель назад
Есть идея записывать айпишники, и при загрузке страницы проверять, голосовал такой или нет, и если да — обзывать нужный div по-другому, чтобы кнопка была неактивна.
Саму проверку «голосовал или нет» лучше реализовать в момент попытки добавления нового голоса, иначе у вас будет бестолковая нагрузка на базу при каждой загрузке страницы + в итоге будет накрутка, т.к. «не нажимающаяся кнопка» совсем не поможет.