php投票系统简单实现源码
数据库的设计: 设计三张表,投票结果统计表(count_voting),投票人记录表(ip_votes),用户表(user).
投票结果统计表用于统计最后的投票记录,我给它弄了4个字段:被投票项的名称(SelectName),被投票项标签名(LabelName)(起到分类的作用),票数(CountVotes).
投票人记录表用于登记投票人的ip(IP),地理位置(Location),投票时间(VoteTime),被投票项名称(SelectName),然后我还给它加一个ID.
用户表主要用于给管理员用的,包含用户名(name)和密码(passwd).
生成表的sql脚本如下,代码如下:
-- -- 表的结构 `count_voting` -- DROP TABLE IF EXISTS `count_voting`; CREATE TABLE IF NOT EXISTS `count_voting` ( `SelectName` varchar (40) NOT NULL , `LabelName` varchar (40) NOT NULL , `CountVotes` bigint (20) unsigned NOT NULL , UNIQUE KEY `SelectName` (`SelectName`), KEY `CountVotes` (`CountVotes`), KEY `CountVotes_2` (`CountVotes`), KEY `CountVotes_3` (`CountVotes`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '投票统计表' ; -- -------------------------------------------------------- -- -- 表的结构 `ip_votes` -- DROP TABLE IF EXISTS `ip_votes`; CREATE TABLE IF NOT EXISTS `ip_votes` ( `ID` bigint (20) unsigned NOT NULL auto_increment COMMENT '投票人序号:自增' , `IP` varchar (15) NOT NULL COMMENT '投票人IP' , `Location` varchar (40) NOT NULL COMMENT '投票人位置' , `VoteTime` datetime NOT NULL , `SelectName` varchar (40) NOT NULL , PRIMARY KEY (`ID`), KEY `ID` (`ID`), KEY `SelectName` (`SelectName`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; -- -- 触发器 `ip_votes` -- DROP TRIGGER IF EXISTS `vote_count_after_insert_tr`; DELIMITER // CREATE TRIGGER `vote_count_after_insert_tr` AFTER INSERT ON `ip_votes` FOR EACH ROW UPDATE count_voting SET CountVotes = CountVotes + 1 WHERE SelectName = NEW.SelectName // DELIMITER ; -- -------------------------------------------------------- -- -- 表的结构 `user` -- DROP TABLE IF EXISTS ` user `; CREATE TABLE IF NOT EXISTS ` user ` ( ` name ` varchar (10) NOT NULL COMMENT '管理员用户名' , `passwd` char (32) NOT NULL COMMENT '登录密码MD5值' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '用户表' ; -- -- 转存表中的数据 `user` -- INSERT INTO ` user ` (` name `, `passwd`) VALUES ( 'ttxi' , '700469ca1555900b18c641bf7b0a1fa1' ), ( 'jitttanwa' , 'adac5659956d68bcbc6f40aa5cd00d5c' ); -- -- 限制导出的表 -- -- -- 限制表 `ip_votes` -- ALTER TABLE `ip_votes` ADD CONSTRAINT `ip_votes_ibfk_1` FOREIGN KEY (`SelectName`) REFERENCES `count_voting` (`SelectName`) ON DELETE CASCADE ON UPDATE CASCADE ;从脚本中可以看出,我创建了一个触发器,当往ip_votes表中插入数据的时候就给count_voting表中的CountVotes字段加1,还能后出最后一句是设置外部关联字.
框架设计: OperatorDB类用于操作数据库,OperatorVotingDB类用于该系统特定的操作集合,使用PDO操作数据库,我它简单的封装一下,代码如下:
/** * 操作数据库 * 封装PDO,使其方便自己的操作 */ class OperatorDB { //连接数据库的基本信息 private $dbms = 'mysql' ; //数据库类型,对于开发者来说,使用不同的数据库,只要改这个. private $host = 'localhost' ; //数据库主机名 private $dbName = 'voting' ; //使用的数据库 private $user = 'voting' ; //数据库连接用户名 private $passwd = 'voting' ; //对应的密码 private $pdo =null; public function __construct() { //dl("php_pdo.dll"); //dl("php_pdo_mysql.dll"); $this ->dsn= "$this->dbms:host=$this->host;dbname=$this->dbName" ; try { $this ->conn= new PDO( $this ->dsn, $this ->user, $this ->passwd); //初始化一个PDO对象,就是创建了数据库连接对象$db } catch(PDOException $e ) { die ( "<br/>数据库连接失败(creater PDO Error!): " . $e ->getMessage(). "<br/>" ); } } public function __destruct() { $this ->pdo = null; } public function exec ( $sql ) { } public function query( $sql ) { } }把连接数据库的信息封装进去方便后续的操作,代码如下:
<?php require_once 'OperatorDB.php' ; class OperatorVotingDB { private $odb ; public function __construct() { $this ->odb = new OperatorDB(); } public function __destruct() { $this ->odb = null; } /** * 清空Voting数据中的所有表 * * 调用数据库操作类,执行clear数据库的操作 */ public function clearTables() { $sqls = array ( "TRUNCATE ip_votes;" , "TRUNCATE count_voting;" ); $this ->odb-> exec ( $sqls [0]); $this ->odb-> exec ( $sqls [1]); } /** * 重置count_voting表中的CountValues字段为0 * */ public function resetCountValues() { $sql = "UPDATE count_voting SET CountVotes = 0;" ; $this ->odb-> exec ( $sql ); } /** * 投票 * 将信息写入ip_votes表 * @param type $ip * @param type $loc * @param type $time * @param type $name */ public function vote( $ip , $loc , $name ) { $sql = "INSERT INTO ip_votes VALUES (NULL, '$ip', '$loc', NOW(), '$name')" ; $subsql = "SELECT MAX(to_days(VoteTime)) FROM ip_votes WHERE IP='$ip'" ; $stm = $this ->odb->query( $subsql ); if ( count ( $row = $stm ->fetchAll())==1) { $now = date ( "Y-m-d H:i:s" ); $subsql = "SELECT to_days('$now');" ; $stm = $this ->odb->query( $subsql )->fetch(); $time = $stm [0]; //使用mysql计算出的today时间 // echo $time."<br>"; // echo $row[0][0]; if ( $time - $row [0][0]<1) //表中最大的时间和现在的时间$time比较 { echo "投票失败,相同ip需要隔一天才能投票" ; return ; } } // echo $sql; echo "投票成功!" ; $this ->odb-> exec ( $sql ); } /** * 添加SelectName字段的行 * * @param string $name * @param string $label * @param int $count */ public function addSelectName( $name , $label , $count =0) { $sql = "INSERT INTO count_voting VALUES ('$name', '$label', $count);" ; $this ->odb-> exec ( $sql ); } /** * 获取总投票情况,按票数排序的结果 * * 按CountVotes字段排序,返回count_voting表 * * @param int $n * */ public function getVotesSortByCount( $n =-1) { $sql = "SELECT * FROM count_voting ORDER BY CountVotes DESC LIMIT 0 , $n;" ; if (-1 == $n ) { $sql = "SELECT * FROM count_voting ORDER BY CountVotes DESC;" ; } // echo $sql; return $this ->odb->query( $sql ); } /** * 获取投票情况,按票数排序并按标签分组的结果 * * 按CountVotes字段排序并按LabelName字段分组,返回count_voting表 */ public function getVotesGroupByLabel() { $sql = "SELECT * FROM count_voting ORDER BY LabelName DESC;" ; //开源代码phpfensi测试数据 // echo $sql; return $this ->odb->query( $sql ); } } ?>下面还有需要的函数,代码如下:
<?php /** * 页面跳转函数 * 使用js实现 * @param string $url */ function goToPgae( $url ) { echo "<script language='javascript' type='text/javascript'>" ; echo "window.location.href='$url'" ; echo "</script>" ; } function jsFunc( $fun , $arg =null) { echo "<script language='javascript' type='text/javascript'>" ; echo $fun . "('$arg');" ; echo "</script>" ; } function jsFunc3( $fun , $arg1 =null, $arg2 =null, $arg3 =null) { echo "<script language='javascript' type='text/javascript'>" ; echo $fun . "('$arg1','$arg2','$arg3');" ; echo "</script>" ; //echo $fun."('$arg1','$arg2','$arg3');"; } function isLoginNow() { if ( $_COOKIE [ "user" ]== '' ) { return false; } return true; } function getClientIP() { if ( $_SERVER [ "HTTP_X_FORWARDED_FOR" ]) { if ( $_SERVER [ "HTTP_CLIENT_IP" ]) { $proxy = $_SERVER [ "HTTP_CLIENT_IP" ]; } else { $proxy = $_SERVER [ "REMOTE_ADDR" ]; } $ip = $_SERVER [ "HTTP_X_FORWARDED_FOR" ]; } else { if ( $_SERVER [ "HTTP_CLIENT_IP" ]) { $ip = $_SERVER [ "HTTP_CLIENT_IP" ]; } else { $ip = $_SERVER [ "REMOTE_ADDR" ]; } } return $ip ; } //从123查获取ip function getIpfrom123cha( $ip ) { $url = 'http://HdhCmsTest123cha测试数据/ip/?q=' . $ip ; $content = file_get_contents ( $url ); $preg = '/(?<=本站主数据:</li><li style="width:450px;">)(.*)(?=</li>)/isU' ; preg_match_all( $preg , $content , $mb ); $str = strip_tags ( $mb [0][0]); //$str = str_replace(' ', '', $str); $address = $str ; if ( $address == '' ) { $address = '未明' ; } return $address ; } //从百度获取ip所在地 function getIpfromBaidu( $ip ) { $url = 'http://HdhCmsTestbaidu测试数据/s?wd=' . $ip ; $content = file_get_contents ( $url ); $preg = '/(?<=<p class="op_ip_detail">)(.*)(?=</p>)/isU' ; preg_match_all( $preg , $content , $mb ); $str = strip_tags ( $mb [0][1]); $str = str_replace ( ' ' , '' , $str ); $address = substr ( $str , 7); if ( $address == '' ) { $address = '未明' ; } return $address ; } ?>然后就是后台管理员的操作怎么弄了,主要是添加投票项的功能,操作数据库上面已经实现,后面的基本上是页面怎么设置,关系到js,添加投票项的页面是动态的,代码如下:
function addVote() { right.innerHTML= "<h2>添加投票项</h2>" ; right.innerHTML+= "<label>投票项标签<label>" ; addInput( "right" , "cLabelName" , "地区名" ); right.innerHTML+= "<br><label>投票项名称<label>" ; addInput( "right" , "cSelectName" , "学校名" ); right.innerHTML+= "<br>" ; var args = '' ./add.php ',' cSelectName ',' cLabelName '' ; var str = '<input type=button value="u6dfb加" onclick="goToPage(' +args+ ');"/>' ; right.innerHTML+=str; } //添加文本框 function addInput(parent,id,pla) { //创建input var input = document.createElement( "input" ); input.type = "text" ; input.id = id; input.placeholder = pla; document.getElementById(parent).appendChild(input); }添加投票项是通过url传递变量到add.php页面的,代码如下:
<?php require_once 'api/func.php' ; if (!isLoginNow()) { goToPgae( "./index.php" ); } $name = $_GET [ "cSelectName" ]; $label = $_GET [ "cLabelName" ]; //echo $name."<br>".$label; require_once 'api/OperatorVotingDB.php' ; $ovdb = new OperatorVotingDB(); $ovdb ->addSelectName( $name , $label ); require './header.htm' ; goToPgae( "./admin.php?page=add&auto=" . "$label" . "&id=cLabelName&foc=cSelectName&msg=添加成功" ); ?>下面是两个跳转页面的函数,js的,上面func.php中的跳转页面函数也是通过js实现的,代码如下:
//js function goToPage(url,arg1,arg2) { var a = document.getElementById(arg1).value; var b = document.getElementById(arg2).value; url += '?' +arg1+ '=' +a; url += '&' +arg2+ '=' +b; window.location.href=url; } function goToPage1(url) { window.location.href=url; }还有修改删除功能没有实现,我应该不会去实现那个了吧,js的话和添加功能差不多.
登录模块的话网上很多,模仿的,就是提交表单,查找数据库,返回结果,成功则设置cookie,后台的每个页面都添加了检测cookie的功能的.
查看更多关于php投票系统简单实现源码 - 综合实例的详细内容...