PHP/MYSQL разрешает только один голос каждому участнику?
-
07-07-2019 - |
Вопрос
На работе мне дали задание настроить систему голосования за награды, я не особо разбираюсь в php и mysql.Но я знаю об этом больше, чем кто-либо здесь, а мой босс в отпуске.Но я повторно использовал код, который ранее оставался в нашей системе, и адаптировал его к этому году.
В принципе система голосования работает нормально, и я создал новые таблицы в MySQL для сбора данных.Однако я обнаружил один довольно большой недостаток в существующем коде и не знаю, как его изменить.По сути, код позволяет людям голосовать столько раз, сколько они хотят в данный момент.Я хочу ограничить его только одним голосом на каждого участника, чтобы все было честно.
Итак, на данный момент участники входят в систему, используя номер членства, а затем голосуют.Голоса хранятся в таблицах MySQL, и затем я могу суммировать голоса, запросив данные.
Я надеялся, что кто-нибудь поможет мне добавить пару строк кода, которые просто проверят, проголосовал ли уже участник.Когда участник голосует, его номер участника.хранится в таблицах sql вместе с выбранными ими голосами.Так что, возможно, лучший способ — посмотреть, существует ли уже мемберид в таблице, и если да, то сообщить пользователю, что он уже проголосовал, или сказать что-то подобное.
<?php
//Insert into volunteer awards
$coach=mysql_real_escape_string($_SESSION['coach']);
$official=mysql_real_escape_string($_SESSION['official']);
$young_volunteer=mysql_real_escape_string($_SESSION['young_volunteer']);
$volunteer=mysql_real_escape_string($_SESSION['volunteer']);
$memberid=$_SESSION['MM_Username'];
$association=$_SESSION['MM_Association'];
$region=$_SESSION['Region'];
$sql_query = mysql_query("INSERT INTO awards_2009_votes (`id`, `member_id`, `region`, `coach`, `official`, `volunteer`, `young_volunteer`) VALUES ('', '$memberid', '$region', '$coach', '$official', '$volunteer', '$young_volunteer')") or die (mysql_error());
?>
Спасибо
Решение
Вот быстрый и грязный подход:
$sql_query = "SELECT FROM awards_2009_votes WHERE member_id = '$memberid'";
$sql_result = mysql_query($sql_query);
$num_rows = mysql_num_rows($sql_result);
if ($num_rows > 0) {
// this member has already voted
} else {
// carry on
}
Однако, как отметил Писквор, это решение имеет (как минимум) два ограничения:
- Он ограничен методом, содержащим его, поэтому не предотвращает множественное голосование. в общем - только с помощью этого конкретного метода.(Вы можете написать функцию, содержащую ту же самую проверку, но вам все равно придется вызывать эту функцию везде, где пользователь пытается проголосовать.)
- Это приводит к дополнительной нагрузке на базу данных, что может быть неприемлемо в сценарии с высоким трафиком.
Учитывая это, я рекомендую сначала запустить скрипт для проверки наличия повторяющихся значенийmember_id в вашей таблице голосов, удалить все, кроме одного, в каждом случае, а ЗАТЕМ добавить ограничение UNIQUE в вашу таблицу.Отсюда вы можете быть уверены, что в вашей таблице никогда не будет более одной строки с одним и тем жеmember_id.
Другие советы
Вы можете добавить ограничение UNIQUE в свою таблицу.Это одноразовая операция — вам не нужно делать это каждый раз при запуске скрипта, это изменение структуры таблицы.Запустите это в своем инструменте администрирования MySQL (например,phpMyAdmin, Navicat, HeidiSQL, что у вас есть):
ALTER TABLE awards_2009_votes ADD UNIQUE (member_id);
После этого изменения будет невозможно добавить второй голос с тем же идентификатором участника — операция INSERT (или UPDATE) завершится неудачей.
Преимущество здесь в том, что проверка выполняется автоматически в базе данных, поэтому вам не нужно беспокоиться о 1) проверке дубликатов вашего кода или 2) о том, что люди добавляют несколько голосов вручную.
Как @Миддапарка говорит, вам следует использовать INSERT IGNORE
чтобы избежать ошибки «дубликат ключа»:
$sql_query = mysql_query("INSERT IGNORE INTO awards_2009_votes (`member_id`, `region`, `coach`, `official`, `volunteer`, `young_volunteer`) VALUES ('$memberid', '$region', '$coach', '$official', '$volunteer', '$young_volunteer')") or die (mysql_error());
if (mysql_insert_id()) {
// row was inserted - vote added
} else {
// row was not inserted - already voted
}
Судя по вашему коду, я не уверен, какова структура вашей таблицы, но следующая структура таблицы ограничит голосование пользователей одним голосом за тему:
Таблица пользователей
user_id int unsigned not null auto_increment,
username varchar
// and other user info fields
Таблица тем
topic_id int unsigned not null auto_increment,
topic_title varchar
// and other topic info fields
Стол для голосования
user_id,
topic_id,
vote_value,
primary key (user_id,topic_id) //this is the constraint that will allow only one vote
Вы можете написать несколько строк следующим образом, хотя я это не проверял, но они должны работать...
$result=mysql_query("select count(*) count from awards_2009_votes where member_id='$memberid'");
$has_voted_array=mysql_fetch_array($result);
if($has_voted['count']!=0)
echo "You have already registered youur vote";
else
{
//do normal operation
$sql_query = mysql_query("INSERT INTO awards_2009_votes (id, member_id, region, coach, official, volunteer, young_volunteer) VALUES ('', '$memberid', '$region', '$coach', '$official', '$volunteer', '$young_volunteer')") or die (mysql_error());
}