PHP/MYSQL只允许每个成员投一票?
我一直在做建立奖项投票系统的工作,我对php和mysql不太了解。但我比这里的任何人都了解这一点,我的老板也在度假。但我一直在重用以前留在我们系统上的代码,并在今年对其进行了调整 基本上,投票系统工作正常,我在mysql中设置了新的表来捕获数据。不过,我在现有代码中发现了一个相当大的缺陷,不知道如何修改它。基本上,该准则允许人们在此刻随意投票。为了公平起见,我想限制每个成员只投一票 因此,目前,会员使用会员号码登录,然后投票。投票被存储在mysql表中,然后我可以通过查询数据将投票相加 我希望有人能帮我添加一两行代码,这将只是检查一个成员是否已经投票。当一个成员投票时,其成员编号与投票选择一起存储在sql表中。因此,最好的方法可能是查看表中是否已经存在Memebrid,如果已经存在,请告诉用户他们已经投票了,或者说已经投票了PHP/MYSQL只允许每个成员投一票?,php,mysql,voting-system,Php,Mysql,Voting System,我一直在做建立奖项投票系统的工作,我对php和mysql不太了解。但我比这里的任何人都了解这一点,我的老板也在度假。但我一直在重用以前留在我们系统上的代码,并在今年对其进行了调整 基本上,投票系统工作正常,我在mysql中设置了新的表来捕获数据。不过,我在现有代码中发现了一个相当大的缺陷,不知道如何修改它。基本上,该准则允许人们在此刻随意投票。为了公平起见,我想限制每个成员只投一票 因此,目前,会员使用会员号码登录,然后投票。投票被存储在mysql表中,然后我可以通过查询数据将投票相加 我希望有
<?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
}
然而,正如Piskvor所指出的,该解决方案(至少)有两个局限性:
它仅限于包含它的方法,因此它一般不会阻止多次投票——只通过这个特定的方法。(您可以编写一个函数来包含相同的检查,但仍然必须在用户尝试投票的任何地方调用该函数。)
这会对数据库造成额外的压力,这在高流量场景中可能是不可接受的
考虑到这些要点,我的建议是首先运行一个脚本来检查投票表中是否出现重复的member_id值,在每种情况下删除除一个以外的所有值,然后将唯一约束添加到表中。从那里,您可以确保您的表中永远不会有多个具有相同成员id的行。您可以向表中添加唯一约束。这是一个一次性操作-您不需要每次运行脚本时都这样做,这是对表结构的更改。在您的MySQL管理工具(例如phpMyAdmin、Navicat、HeidiSQL)中运行此命令:
更改后,将无法使用相同的成员ID添加第二次投票-插入(或更新)将失败
这里的优点是,检查是在数据库中自动完成的,因此您不必担心1)使用代码检查重复项,或2)人们手动添加多张投票
正如@所说,您应该使用INSERT IGNORE
来避免出现“重复键”错误:
从您的代码中,我不确定您的表结构是什么,但以下表结构将用户投票限制为每个主题一票:
用户表
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
主题表
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
投票表
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());
}
您还需要将选票插入更改为使用INSERT IGNORE以避免生成重复的密钥错误,但这似乎是我认为最好的方法。正如MySQL文档(INSERT IGNORE的第一个Google结果)所述:如果使用IGNORE关键字,则执行INSERT语句时发生的错误将被视为警告。例如,在不忽略的情况下,复制表中现有唯一索引或主键值的行将导致重复键错误,语句将中止。使用IGNORE时,仍不会插入行,但不会发出错误。“插入忽略是一个合理的选择。但是如果你想让你的用户改变他们的投票,你可以考虑替换为插入的工作,除非它替换了重复记录会导致的行。@ DNAGRIL -更好的是,如果你使用MySQL 5。x,你可以使用插入…关于重复密钥更新。我知道这个答案很旧,但它意味着未来的读者要注意SQL注入的工作原理——尽管您正在进行额外的db查询。这可能是问题,也可能不是问题,取决于流量等。此外,此检查只会阻止您的特定脚本添加多个投票。是的,您的解决方案更好。在我看来,snoop123可能只是简单地要求以任何方式获得他想要的功能;我(在我看来)提供了最直接的方法。你的回答中的一个潜在问题是,如果一个成员已经投票不止一次,那么它将不起作用;必须首先进入并删除所有重复的行,然后更新表。(当然,考虑到snoop123的要求,这是无论如何都应该做的事情。)我知道这个答案很旧,但它的意思是让未来的读者注意SQL注入。我知道这个答案很旧,但它的意思是让未来的读者注意SQL注入