基于PHP和DOMDocument的无数据库投票系统

在这个数字化时代,投票系统已经成为网站互动的重要组成部分。无论是音乐网站、新闻门户还是社区论坛,用户投票都是收集用户意见、增加用户参与度的有效方式。然而,传统的投票系统往往依赖数据库存储投票结果,这不仅增加了系统的复杂性,还可能导致数据安全问题。本文将介绍一种基于PHP和DOMDocument的无数据库投票系统,该系统通过XML文件存储投票结果,并通过IP地址防止重复投票,从而提供了一种简单、安全且高效的投票解决方案。

运营着一个本地音乐网站,每个月都希望会员们能够投票选出他们最喜欢的本地乐队。然而,Joomla的默认投票应用会在cookie中记录IP地址,这意味着用户只需删除cookie就可以再次投票,这种不公平的系统使得投票结果容易被操纵。因此,开始在网上寻找第三方组件,希望能够记录IP地址并确保用户每天只能投票一次。

经过一番搜索,发现现有的解决方案要么速度极慢,要么需要电子邮件注册(意味着加入垃圾邮件列表),或者带有各种弹出广告。无奈之下,决定重拾PHP技能,自己编写投票系统。虽然更擅长ASP.NET和C#,但对PHP也有一定的了解。因此,在阅读本文时,请记住并非PHP领域的专家。

快速入门

幸运的是,运行这个投票系统只需要PHP 5.0。这是因为DOMDocument对象是PHP 5的新特性。不需要任何数据库系统,因为这个投票系统使用简单的文件I/O和XML。

如果想要跳过教程,以下是快速安装指南。如果想知道程序的详细工作原理,请继续阅读!

  1. 创建一个目录,用于存放投票系统。这可以是根Web目录。
  2. 将.zip文件中的文件解压缩到上述目录。
  3. 将/xml目录下的addresses.xml和results.xml的权限设置为777。
  4. 打开results.xml文件,添加投票问题,以及每个投票项的条目。
  5. 将results.xml文件中的投票计数设置为零(或者希望的起始值)。
  6. 可选:修改poll.css文件以适应网站主题。
  7. 通过http://www.yoursite.com/yourpolldirectory/poll.php访问投票。

就是这样!请注意,addresses.xml文件中至少应该有1个地址条目(127.0.0.1的回环地址即可)。

系统概述

PHP投票系统非常简单,它包含4个PHP文件、2个XML文件和一个样式表。从技术上讲,用户只会看到其中的两个页面,它们如下所示:

  • poll.php:调用loadpoll.php来显示投票选项。
  • results.php:调用savevote.php来显示投票结果。

loadpoll.php负责显示投票。它的工作原理非常简单:

  1. 使用DOMDocument加载results.xml文件。
  2. 遍历所有的pollitem节点以获取投票项。
  3. 为每个项目创建一个单选按钮控件,并为特定条目分配值。
$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) { // 创建一个单选按钮... }

基本上只是使用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("请在投票前选择一个条目。"); return false; } }

savevote.php是最大的文件,也是工作量最大的文件。操作顺序如下:

  1. 请求"votefor"的值。
  2. 如果有$votefor的空值,只显示结果。
  3. 使用$_SERVER["REMOTE_ADDR"]全局变量获取提交者的IP。
  4. 加载addresses.xml文件,并循环检查是否有匹配的IP地址。
  5. 如果有匹配项,检查最后一次投票的日期。
  6. 如果日期是今天,不计算投票(用户已经投票)。
  7. 如果不是今天,在results.xml中增加投票计数,并设置最后一次投票日期为今天。
  8. 如果没有匹配项,添加新的地址节点,包含IP和今天的日期。
  9. 现在已经计算了投票(或者没有,视情况而定),显示结果。

更高级的功能

显示结果可以很简单,一个带有“条目:xx票”的单行项目就足够了。但是,想变得更聪明。喜欢显示一个折线图,折线图内显示投票百分比的想法。现在,不必这样做,但如果对如何做到这一点感兴趣,请继续阅读。

首先,需要图表的总票数。在代码中,这样获取它:

// 获取最大投票计数 $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文件以计算百分比。

// 生成结果表 $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 "$entry"; echo "
$votepct%
($vote votes)"; }

所做的就是创建一个包含三列的表格。第一列将包含条目名称,第二列将有折线图和百分比,最后一列将包含总票数。

创建图表的方法是为每个条目创建一个DIV对象。基础是DIV的最大宽度将是300px。可以将其设置为任何喜欢的值,只要确保它适合表格和页面!所以,要得到DIV的宽度,只需要取票数($vote),除以最大票数($maxvote),然后将该百分比值乘以300。假设有30票,总共100票,30/100 = 0.3,0.3 * 300 = 90,DIV需要90像素宽。然后,要得到百分比(放在DIV中间),只需要取$vote/$maxvote,四舍五入值,然后乘以100。使用上述示例,这将给30%。

现在,当创建每个DIV时,知道要制作每个DIV的宽度,以及要放在DIV中间的%值。认为为每个div创建不同的颜色会很酷,所以写了一个getRandomColor()函数,并将DIV的background-color样式设置为该函数返回的任何值。

// 返回一个随机的RGB颜色(用于给投票条上色) function getRandomColor() { $r = rand(128, 255); $g = rand(128, 255); $b = rand(128, 255); $color = dechex($r) . dechex($g) . dechex($b); echo "$color"; }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485