一个简单的 PHP 投票系统






4.58/5 (25投票s)
2006年12月11日
7分钟阅读

403511

15056
使用 PHP 5.0 创建一个 IP 日志记录的 PHP 投票系统
引言
本文将演示如何使用 PHP 5.0 和 DOMDocument 对象模型创建一个非常简单、干净的投票系统。这使得投票系统能够将投票结果读取和写入 XML 文件,而不是像许多传统的投票系统那样使用 MySQL 数据库。
背景
我运行着一个本地音乐网站,每个月我都想让我的会员投票选出他们最喜欢的本地乐队。问题在于 Joomla 的默认投票应用程序会在 cookie 中记录 IP 地址。所以,用户只需删除 cookie 就可以再次投票。这是一个非常不公平的系统,允许操纵投票箱。因此,我开始在网上搜索一个可以记录 IP 地址并阻止人们每天投票多次的第三方组件。
在网上搜索了很长时间后,我发现找不到任何能够让我 1) 拥有超过 10 个投票项,以及 2) 将 IP 地址记录到数据库或文件中以确保人们无法每天投票多次的可靠组件。我找到的那些符合我需求的组件,要么非常缓慢,要么需要电子邮件注册(也就是说,把我加入垃圾邮件列表),要么它们的组件附带各种弹窗广告。
非常沮丧,我选择重新拾起我的 PHP 技能,自己编写一个。现在,那些读过我上一篇文章的人都知道我是一个微软技术专家,专注于 ASP.NET 和 C#。不是 PHP!但我确实有一些该语言的经验(是的,我真的很喜欢 PHP 的简洁/强大),所以,在阅读本文时,请记住,我绝不是 PHP 方面的专家!
此投票系统易于部署和配置,并希望为您那些只想在短时间内运行安全投票的人提供一定的帮助!
入门
幸运的是,运行此投票系统只需要 PHP 5.0。这是一个要求,因为 DOMDocument 对象是 PHP 5 新增的。您不需要任何数据库系统,因为此投票系统利用简单的文件 I/O 和 XML。
如果您想跳过教程,我将在下面提供快速入门说明。如果您想确切地了解程序中发生的事情,请继续阅读!
快速安装
- 为投票系统创建一个目录。如果需要,可以将其放在您的根 Web 目录中。
- 将 .zip 文件中包含的文件解压到上述目录。
- 将 addresses.xml 和 results.xml 文件 CHMOD 为 777(在 /xml 目录下)
- 打开 results.xml 文件,并添加您的投票问题以及每个投票项的条目。
- 将 results.xml 文件中的投票数设置为零(或您想开始的任何数字)。
- 可选:修改 poll.css 文件以适应您网站的主题。
- 通过 http://www.yoursite.com/yourpolldirectory/poll.php 访问投票系统
- 就是这样!请注意,addresses.xml 文件中至少应有 1 个地址条目(127.0.0.1 的回路地址也可以)。
访问您的投票系统后,poll.php 屏幕将显示如下内容
投票后,结果屏幕将显示如下内容
概述
PHP 投票系统很简单。它包含 4 个 PHP 文件、2 个 XML 文件和一个样式表。技术上,用户只会看到其中两个页面。它们在下面概述。
- Poll.php
- 调用 loadpoll.php 来显示投票选项
- Results.php
- 调用 savevote.php 来显示投票结果
Loadpoll.php 处理投票的显示。它的处理方式很简单。
- 使用 DOMDocument 加载 results.xml 文件
- 循环遍历所有 pollitem 节点以获取投票的条目
- 为每个条目创建一个单选按钮控件,并将值分配给特定条目
$doc = new DOMDocument(); $doc->load("xml/results.xml"); $root = $doc->getElementsByTagName("results")->item(0); $question = $root->getAttribute("question"); $pollitems = $doc->getElementsByTagName("pollitem"); foreach( $pollitems as $pollitem ) { //Create a radio button... }
我们基本上只使用 DOMDocument 对象提供的可用方法来循环遍历节点,然后发出一些 HTML 来处理我们的单选按钮控件。最后一步是设置单选按钮 onclick 事件上的 JavaScript。它的作用是用投票的值填充隐藏输入字段的文本。这样,我们可以通过简单的 JavaScript confirm() 对话框来确保设置了值。如果没有,我们将不提交投票。一旦我们设置了该值,然后单击“投票”,表单(action="savevote.php")的值会将隐藏值发布到 savevote.php。JavaScript 函数如下所示。
function setVote(voteName) { document.getElementById("votefor").value = voteName; } function confirmSubmit() { if (document.getElementById("votefor").value == "") { var agree=confirm("Please select an entry before voting."); return false; } }
在 PHP 中,POST 和 GET 变量被加载到 $_REQUEST 全局变量中。因此,在 savevote.php 中,我们将请求“votefor”值,该值已在 poll.php 页面中设置。
$votefor = $_REQUEST["votefor"];
Savevote.php 是最大的文件,也是工作量最大的文件。操作顺序如下
- 请求“votefor”的值
- 如果 $votefor 的值为 null,我们只显示结果。
- 使用 $_SERVER["REMOTE_ADDR"] 全局变量获取提交者的 IP 地址
- 加载 addresses.xml 文件,并循环以查看是否有匹配的 IP 地址
- 如果有匹配项,我们将检查上次投票的日期
- 如果日期是今天,我们不计入投票(用户已投票)
- 如果不是今天,我们将投票数加一(在 results.xml 中),并将上次投票日期设置为今天
- 如果我们没有找到匹配项,我们将添加带有 IP 和今天的日期的新地址节点
- 如果有匹配项,我们将检查上次投票的日期
- 现在我们已经计算了投票(或者没有),我们显示结果。
变得花哨
显示结果本来可以很简单。一行显示“条目:xx 票”就足够了。但我希望变得巧妙。我喜欢显示折线图的想法,并在折线图中显示投票百分比。现在,您不必这样做,但如果您有兴趣了解如何做到这一点,请继续阅读。
显示折线图
图表所需的第一件事是总票数。在代码中,我这样获取
// Get max vote count $doc = new DOMDocument(); $doc->load("xml/results.xml"); $maxvotes = 0; $pollitems = $doc->getElementsByTagName("pollitem"); foreach( $pollitems as $pollitem ) { $votes = $pollitem->getElementsByTagName("votes"); $vote = $votes->item(0)->nodeValue; $maxvotes = $maxvotes + $vote; }
现在我们有了最大值,我们将再次循环遍历 results.xml 文件来计算百分比。
// Generate the results table $doc = new DOMDocument(); $doc->load("xml/results.xml"); $pollitems = $doc->getElementsByTagName("pollitem"); foreach( $pollitems as $pollitem ) { $entries = $pollitem->getElementsByTagName("entryname"); $entry = $entries->item(0)->nodeValue; $votes = $pollitem->getElementsByTagName("votes"); $vote = $votes->item(0)->nodeValue; $tempWidth = $vote / $maxvotes; $tempWidth = 300 * $tempWidth; $votepct = round(($vote / $maxvotes) * 100); echo "<tr><td width=\"30%\" class=\"polls\">$entry</td>"; echo "<td width=\"50%\" class=\"resultbar\"><div class=\"bar\" style=\"background-color: "; getRandomColor(); echo "; width: $tempWidth px;\">$votepct%</div></td><td width=\"20%\" ($vote votes)</td></tr>"; }
我的做法是创建一个包含三列的表。第一列将显示条目名称,第二列将是带有百分比的折线图,最后一列将显示总票数。
创建图表
我创建图表所做的就是为每个条目创建一个 DIV 对象。我的基本思想是 DIV 的最大宽度为 300 像素。您可以将其设置为任何您喜欢的值,只要确保它能放入表格和页面即可!所以,要得到 DIV 应该有多宽,我们将取票数($vote),除以最大票数($maxvote),然后将该百分比值乘以 300。所以,假设我们有 100 票中的 30 票,30/100 = .3,.3 * 300 = 90,DIV 需要 90 像素宽。然后,要得到百分比(放在 DIV 中),我们只需取 $vote/$maxvote,四舍五入该值,然后乘以 100。使用上面的例子,这将得到 30%。
为图表着色
现在,当我们创建每个 DIV 时,我们知道每个 DIV 需要多宽,以及放在 DIV 中间的百分比值。我想到为每个 DIV 创建不同的颜色会很酷,所以我编写了一个 getRandomColor() 函数,并将 DIV 的 background-color 样式设置为该函数返回的任何值。
// Returns a random RGB color (used to color the vote bars) function getRandomColor() { $r = rand(128,255); $g = rand(128,255); $b = rand(128,255); $color = dechex($r) . dechex($g) . dechex($b); echo "$color"; }
我们现在所做的就是使用 PHP rand() 函数为红色($r)、绿色($g)和蓝色($b)值获取一个随机值,然后使用 dechex() 函数将十进制值转换为十六进制。这将返回一个格式为十六进制的颜色值,background-color 将接受该格式。
结论
因此,只需几个简单的文件,您就可以在支持 PHP 5.0 的 Web 服务器上拥有一个自定义的投票系统。我能够轻松地在 IIS 5.1 和 Apache 中执行此操作。好处是您不需要数据库来存储记录的 IP 地址。根据我的经验,使用 PHP 5 中的 DOMDocument 对象,此系统运行速度非常快。您可以在实际应用程序中看到此投票功能演示,网址为 www.jaxrock.com/poll/poll.php。
祝您好运,编码愉快!