文章教程

10.3.1系统功能分析及数据库设计

9/17/2020 9:38:49 PM 人评论 次浏览

10.3 设计“网络投票系统”实例

投票系统也是比较流行的一种常用Web应用系统,通常可以用来统计网友对网站设计或时事新闻的态度。本节介绍一个简单的网络投票系统的设计过程。

10.3.1 系统功能分析及数据库设计

网络投票系统模块的关系如图10-9所示。“系统管理员”用户Admin可以创建、修改和删除投票项目;普通用户则只能修改自己的用户名和密码。用户只有登录后,才能够实现管理投票项目的功能。由于篇幅所限,本实例不设计用户管理模块,读者可以参照10.2小节中的用户管理和登录模块理解。

figure_0200_0277

图10-9 网络投票系统的模块关系图

在设计数据库表结构之前,首先要创建一个数据库。本系统使用的数据库为Vote。在数据库Vote中创建两个表,即表VoteItem和表VoteIP。

表VoteItem用来保存需要投票的项目信息,结构如表10-7所示。

表10-7 表VoteItem的结构

figure_0200_0278

表VoteIP用来保存已经投票的IP地址,结构如表10-8所示。

表10-8 表VoteIP的结构

figure_0201_0279

创建数据库的脚本如下:

CREATE DATABASE IF NOT EXISTS Vote

COLLATE 'gb2312_chinese_ci';

USE Vote;

CREATE TABLE IF NOT EXISTS Users (

Id INT AUTO_INCREMENT PRIMARY KEY,

Item VARCHAR(50),

VoteCount INT

);

CREATE TABLE IF NOT EXISTS VoteIP (

IP VARCHAR(50) PRIMARY KEY

);

此段脚本保存为下载源代码的10\Vote\vote.sql。

10.3.2 设计投票项目管理模块

系统管理员可以添加、修改和删除投票项目。设计投票项目管理的文件为 AddItem.PHP,界面如图10-10所示。

figure_0201_0280

图10-10 投票项目管理界面

下面对AddItem.PHP中的代码进行分析。

1.显示项目

从数据库表VoteItem中提取并显示投票项目信息的代码如下:

<table border="1" cellspacing="0" width="90%"  bordercolorlight="#4DA6FF"bordercolordark="#ECF5FF" style="FONT-SIZE: 9pt">

<tr>

<td width="60%" align="center" bgcolor="#FEEC85"><strong>项目</strong></td>

<td width="20%" align="center" bgcolor="#FEEC85"><strong>修改</strong></td>

<td width="20%" align="center" bgcolor="#FEEC85"><strong>选择</strong></td>

</tr>

<?PHP

$hasData = false; // 记录$results中是否存在记录

$results = $obj->load_VoteItem();

while($row = $results->fetch_row()) {

$hasData = true;

?>

<tr><td> <?PHP echo($row[1]);?> </td>

<td  align="center"><a  href="AddItem.php?Oper=update&id=<?PHPecho($row[0]);?>&name=<?PHP echo($row[1]); ?>">修改</a></td>

<td align="center"><input type="checkbox" name="voteitem" id=<?PHP echo($row[0]); ?>></td> </tr>

<?PHP

}

if(!$hasData) {

?>

<tr><td colspan=3 align=center><font style="COLOR:Red">目前还没有投票项目。</font></td></tr></table>

<?PHP } ?>

</table>

程序调用$obj->load_VoteItem()函数获取所有项目,结果集保存在$results中。然后使用while循环语句将$results中的记录输出到表格中。

2.读取参数值

url中参数oper表示要执行的操作,参数id表示操作的项目编号。获取url中参数的代码如下:

$Soperate = $_GET["Oper"]; //操作标记

$Operid = $_GET["id"]; //项目编号

参数oper表示的操作如表10-9所示。

表10-9 参数oper表示的操作

figure_0202_0281

请结合下面的代码理解这些参数的使用方法。

if($Soperate=="add") { // 添加项目

$newTitle = $_POST["txttitle"];

echo($newTitle);

//判断数据库中是否存在此类别

if($obj->exists($newTitle))

echo("已经存在此投票项目,添加失败!");

else {

$obj->Item = $newTitle;

$obj->insert();

echo("投票项目已经成功添加!");

}

}

elseif($Soperate == "edit") { //修改项目

$newTitle = $_POST["txttitle"];

$orgTitle = $_POST["sOrgTitle"];

echo("newTitle : " . $newTitle . " orgTitle: " . $orgTitle);

//如果新类别名称和旧的不同则执行

if($newTitle<>$orgTitle) {

//判断数据库中是否存在此类别

if($obj->exists($newTitle))

echo("已经存在此投票项目,添加失败!");

else {

$obj->updateItem($newTitle, $Operid);

echo("投票项目已经成功修改!");

}

}

}

elseif($Soperate=="delete") { // 删除项目

$obj->delete($Operid);

echo("投票项目已经成功删除!");

}

3.添加项目

单击“添加”按钮,可以添加新的投票项目,并且提交表单。表单提交代码如下:

<form name="AForm" method="post" action="AddItem.PHP?Oper=add">

可以看到,提交数据后的处理脚本还是AddItem.PHP,参数Oper等于add表示添加数据,对应的处理代码如下:

if($Soperate=="add") { // 添加项目

$newTitle = $_POST["txttitle"];

echo($newTitle);

//判断数据库中是否存在此类别

if($obj->exists($newTitle))

echo("已经存在此投票项目,添加失败!");

else {

$obj->Item = $newTitle;

$obj->insert();

echo("投票项目已经成功添加!");

}

}

4.修改项目

单击“修改”按钮,可以修改指定的投票项目,并且提交表单。表单提交代码如下:

<form name="UFrom" method="post" action="AddItem.php?id=<?PHP echo($Operid); ?>&Oper=edit">

可以看到,提交数据后的处理脚本还是AddItem.PHP,参数Oper等于edit表示修改数据,对应的处理代码如下:

if($Soperate=="add") { // 添加项目

……

}

elseif($Soperate == "edit") { //修改项目

$newTitle = $_POST["txttitle"];

$orgTitle = $_POST["sOrgTitle"];

echo("newTitle : " . $newTitle . " orgTitle: " . $orgTitle);

//如果新类别名称和旧的不同则执行

if($newTitle<>$orgTitle) {

//判断数据库中是否存在此类别

if($obj->exists($newTitle))

echo("已经存在此投票项目,添加失败!");

else {

$obj->updateItem($newTitle, $Operid);

echo("投票项目已经成功修改!");

}

}

}

5.删除项目

按钮“全选”和按钮“清空”代码如下:

<input type="button" value="全选" onclick="sltAll()">

<input type="button" value="清空" onclick="sltNull()">

JavaScript函数sltAll()和sltNull()代码如下:

//全部选择

function sltAll() {

var nn = self.document.all.item("voteitem");

for(j=0;j<nn.length;j++) {

self.document.all.item("voteitem",j).checked = true;

}

}

//全部清空

function sltNull() {

var nn = self.document.all.item("voteitem");

for(j=0;j<nn.length;j++) {

self.document.all.item("voteitem",j).checked = false;

}

}

删除项目是通过选中复选框,单击“删除”按钮完成的。代码如下:

<input type="submit" value="删除" name="tijiao" onclick="SelectChk()">

SelectChk()是JavaScript函数,功能是得到要删除的项目的编号,然后删除项目。代码如下:

//选择要删除的项目后,提交表单

function SelectChk(){

var s=false;

var voteitemid,n=0;

var strid,strurl;

var nn = self.document.all.item("voteitem");

for (j=0;j<nn.length-1;j++) {

if (self.document.all.item("voteitem",j).checked){

n = n + 1;

s=true;

voteitemid = self.document.all.item("voteitem",j).id+"";

if(n==1)

strid = voteitemid;

else

strid = strid + "," + voteitemid;

}

}

strurl = "AddItem.PHP?Oper=delete&id=" + strid;

if(!s) {

alert("请选择要删除的投票项目!");

return false;

}

if ( confirm("你确定要删除这些投票项目吗?")) {

form1.action = strurl;

form1.submit();

}

}

可以看到,提交数据后的处理脚本还是AddItem.PHP,参数Oper等于delete表示删除数据,对应的处理代码如下:

if($Soperate=="add") { // 添加项目

……

}

elseif($Soperate == "edit") { // 修改项目

……

}

elseif($Soperate=="delete") { // 删除项目

$obj->delete($Operid);

echo("投票项目已经成功删除!");

}

6.重新投票

单击“重新投票”按钮,程序将清空投票数据。“重新投票”按钮的定义代码如下:

<input type="button" name="revote" value=" 重新投票 " onclick="returnnewwin('ReVote.php')">

重新投票的页面为ReVote.PHP。重新投票就是把所有的投票项目的投票数量改为0,而且删除所有投过票的IP地址。代码如下:

<?PHP

include('Class\VoteItem.php');

$objItem = new VoteItem();

$objItem->clearCount();  // 清空计数

include('Class\VoteIP.php');

$objIP = new VoteIP();

$objIP->deleteAll();    // 删除投票的IP

echo("系统重新投票!");

?>

$objItem.ClearCount()函数的代码如下:

function clearCount() {

$sql = "UPDATE VoteItem Set VoteCount=0 WHERE Id>0";

$this->conn->query($sql);

}

函数中执行UPDATE语句,将VoteCount字段的值设置为0。

$objIP->deleteAll()函数的代码如下:

//删除所有的投票IP

function deleteAll() {

$sql = "DELETE FROM VoteIP";

$this->conn->query($sql);

}

函数中执行DELETE语句,删除VoteIP表中的所有数据。

10.3.3 投票界面设计

投票界面为index.php文件,如图10-11所示。

figure_0206_0282

图10-11 index.php的运行页面

首先判断是否存在投票项目,如果存在就加载项目。代码如下:

<?PHP

$isvoted = 0;

include('Class\VoteIP.php');

include('Class\VoteItem.php');

$objItem = new VoteItem();

$ItemCount = $objItem->getItemCount();

if($ItemCount == 0)

echo("现在没有投票项目");

else {

$results = $objItem->load_VoteItem();

……

?>

程序调用$objItem->getItemCount()函数返回表VoteItem中的项目数量。如果项目数量等于0,则输出“现在没有投票项目”,否则执行下面的内容。

程序会判断当前IP地址是否已经投过票,如果没有投过票,则使用while语句显示所有项目和用于投票的复选框。代码如下:

<?PHP

//取得当前投票人的ip地址,判断是否已经投票完毕

$ip = $_SERVER["REMOTE_ADDR"];

$objIP = new VoteIP();

if($objIP->exists($ip))

$isvoted = 1;

while($row = $results->fetch_row()) {

?>

<tr><td bgcolor="#FFFFFF">

<?PHP if($isvoted==0) { // 如果没有投过票,则显示复选框 ?>

<input type="checkbox" name="poster" id="<?PHP echo($row[0]); ?>">

<?PHP

} // end of if

echo($row[1]); ?></td>

</tr>

<?PHP

} // end of while

?>

如果已经投票(变量$isvoted为1),则显示“查看投票结果”超链接;否则显示投票按钮。代码如下:

<?PHP

//判断是否已经投票完毕

if($isvoted==1) { ?>

您已经投过票了&nbsp;&nbsp;<a href=default.php onclick="return newwin(this. href)"><font color=blue>查看投票结果</font></a>

<?php }

else {

?> <input class=submit type=submit value="投票" name=submit onclick="return SelectChk();">

<?php }

?>

这是一个可以选择多项的投票系统,在 JavaScript函数 SelectChk()中取得被投票项目信息并提交。代码如下:

//取得被投票项目的编号,打开新窗口,查看投票结果

function SelectChk(){

var s=false;

var voteitemid,n=0;

var strid,strurl;

var nn = self.document.all.item("poster");

var j;

for (j=0;j<nn.length;j++) {

if (self.document.all.item("poster",j).checked) {

n = n + 1;

s=true;

voteitemid = self.document.all.item("poster",j).id+"";

if(n==1)

strid = voteitemid;

else

strid = strid + "," + voteitemid;

}

}

strurl = "postvote.php?cid=" + strid;

if(!s) {

alert("请选择投票项目!");

return false;

}

window.open(strurl,"newwin","toolbar=no,location=no,directories=no,status=no,menubar=n o,scrollbars=yes, resizable=yes,width=400,height=300");

return false;

}

投票提交给postvote.php文件,postvote.php会重新取得投票人的IP地址,并判断表VoteIP中是否存在此IP地址,如果没有,则插入此IP地址,并给被投票的项目数值分别加1。代码如下:

<?PHP

$ip = $_SERVER["REMOTE_ADDR"]; //取得投票人的IP地址

include('Class\VoteIP.php');

$objIP = new VoteIP();

//如果表中没有投过票,则插入记录

if($objIP->exists($ip)) {

echo("你已经投过票了,不得重复投票!");

}

else {

$objIP->IP = $ip;

$objIP->insert();

//投票项目数量加1

$ids = $_GET["cid"];

include('Class\VoteItem.php');

$objItem = new VoteItem();

$objItem->updateCount($ids);

echo("已成功投票");

}

?>

$objIP->exists()函数用于判断指定IP地址是否已经参与投票,代码如下:

//判断指定IP是否存在

function exists($_ip)

{

$result = $this->conn->query("SELECT * FROM VoteIP WHERE IP='" . $_ip . "'");

if($row = $result->fetch_row())

return true;

else

return false;

}

$objItem-> updateCount()函数用于将指定编号的项目投票数量加1,代码如下:

function updateCount($Ids) {

$sql = "UPDATE VoteItem SET VoteCount=VoteCount+1 WHERE Id IN (" . $Ids . ")";

$this->conn->query($sql);

}

投过票后再回到index.php,看到的页面如图10-12所示。

figure_0208_0283

图10-12 投票后的index.PHP界面

投票后的可以查看投票结果,链接的代码如下:

<a href=default.php onclick=""return newwin(this.href)"">查看投票结果</a>

newwin()是一个打开新窗口的函数,就是打开default.PHP页面。代码如下:

function newwin(url) {

var oth="toolbar=no,location=no,directories=no,status=no,menubar=no,"

oth = oth + "scrollbars=yes,resizable=yes,left=200,top=200";

oth = oth + ",width=400,height=300";

var newwin=window.open(url,"newwin",oth);

newwin.focus();

return false;

}

default.PHP页面用于显示投票结果,可以查看投票结果和投票比率,如图10-13所示。

figure_0209_0284

图10-13 查看投票结果

投票数百分比的计算代码如下:

<?PHP

//取得这批投票总数

include('Class\VoteItem.php');

$objItem = new VoteItem();

$total = $objItem->SumItemCount();

//取得每个投票项目信息

$results =$objItem->load_VoteItem();

while($row =$results->fetch_row()) {

if($total == 0)

$itotal = 1;

else

$itotal = $total;

//计算每个投票项目百分比图片长度

$imgvote = (int)$row[2] * 170 / $itotal;

?>

<tr><td bgcolor="#FFFFFF"><?PHP echo($row[1]);?></td>

<td colspan="2" bgcolor="#FFFFFF">

<img src=images/bar1.gif width=<?PHP echo($imgvote); ?> height=10><font style="font:7pt" face="Verdana">

<?PHP echo((int)$row[2]*100/$itotal); ?>%</font></td>

<td bgcolor="#FFFFFF" align="center"><?PHP echo($row[2]); ?></td>

</tr>

<?PHP } // end of while ?>

<tr> <td colspan="2" align="left"></td>

<td colspan="2" align="right">总票数:<?PHP echo($total); ?></td>

程序中调用$objItem->SumItemCount()函数计算投票项目的总数量,SumItemCount()函数的代码如下:

function SumItemCount() {

$sql = "SELECT Sum(VoteCount) FROM VoteItem";

$results = $this->conn->query($sql);

if($row = $results->fetch_row())

Return (int)$row[0];

else

Return 0;

}

变量$imgvote用于标识进度图片的宽度,其计算公式如下:

$imgvote = (int)$row[2] * 170 / $itotal;

这里指定图片的总长度为170,$row[2]是表VoteItem的第3个元素(第1个元素为$row[0]),即VoteCount的值,变量$itotal表示记录得到的总投票数量。

教程类别