PHP/MYSQL разрешает только один голос каждому участнику?

StackOverflow https://stackoverflow.com/questions/1426744

  •  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
}

Однако, как отметил Писквор, это решение имеет (как минимум) два ограничения:

  1. Он ограничен методом, содержащим его, поэтому не предотвращает множественное голосование. в общем - только с помощью этого конкретного метода.(Вы можете написать функцию, содержащую ту же самую проверку, но вам все равно придется вызывать эту функцию везде, где пользователь пытается проголосовать.)
  2. Это приводит к дополнительной нагрузке на базу данных, что может быть неприемлемо в сценарии с высоким трафиком.

Учитывая это, я рекомендую сначала запустить скрипт для проверки наличия повторяющихся значений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());
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top