By: GoodOlClint
September 24, 2005
As some of you may or may not know I work in the Technology Ministry of the largest church in the State of Arkansas. One of the projects that got presented to me this week was to re-write an online polling system so we could have more then one poll on our children's website.
I'm going to show you how I did this, I'm not going to include the administration backend, because that would take too much time. but I'll show you how to do the frontend.
First off, I have two files that I use for any project that I make in PHP, one is Config.php the other is mySQL.php.
Let me show you the Contents of config.php already setup for this project:
<?php
if(IsInternal!=1){
die("Cannot access directly!");
}
class Config{
var $DBConfig = array(
"SiteName" => "{YOUR SITE NAME}",
"SiteAddress" => "{YOUR SITE ADDRESS}",
"ContactName" => "{YOUR NAME}",
"ContactEmail" => "{YOUR EMAIL}",
"Database" => "{DATABASE NAME}",
"User" => "{DATABASE USER NAME}",
"Pass" => "{PASSWORD}",
"Host" => "{HOST usually localhost}",
"Port" => "",
"Persistent" => 0
);//DBConfig
var $DBDriver = "mySQL.php";
}
?>
You will need to replace everything in{}'s with your information.
Here is mySQL.php, which we will use to wrap all the built in PHP mysql_ functions.
<?phpif(IsInternal!=1){die("Cannot access directly!");}
class DB {
var $Config = array("SiteName" => "","SiteAddress" => "",
"ContactName" => "",
"ContactEmail" => "",
"Database" => "",
"User" => "root",
"Pass" => "",
"Host" => "localhost",
"Port" => "",
"Persistent" => 0
);//Config
var $ReturnQuery = "";
var $ConnectionID = "";
var $RecordRow = array();
function Connect() {
if (!$this->Config['Persistent']) {
$this->ConnectionId = mysql_connect( $this->Config['Host'] ,
$this->Config['User'] ,
$this->Config['Pass']
);
}else{
$this->ConnectionId = mysql_pconnect( $this->Config['Host'] ,
$this->Config['User'] ,
$this->Config['Pass']
);
} //If !$this->Config['Persistent']
if (!mysql_select_db($this->Config['Database'], $this->ConnectionId)) {
$this->Error("Cannot find database ".$this->Config['Database']);
}//if !mysql_select_db
}//Connect
function Query($Query="") {
$this->ReturnQuery = mysql_query($Query, $this->ConnectionId);
if (!$this->ReturnQuery) {
$this->Error("mySQL query error: $Query");
}//!$this->query_id
return $this->ReturnQuery;
}//Query
function FetchRow() {
$this->RecordRow = mysql_fetch_array($this->ReturnQuery, MYSQL_ASSOC);
return $this->RecordRow;
}//FetchRow
function GetAffectedRows() {
return mysql_affected_rows($this->ConnectionId);
}//GetAffectedRows
function GetNumRows() {
return mysql_num_rows($this->ReturnQuery);
}//GetNumRows
function CloseDB() {
return mysql_close($this->ConnectionId);
}//CloseDB
function FreeResult() {
@mysql_free_result($this->ReturnQuery);
}//FreeResult
function Error($Message="") {
if(!$Message){
print("A database error has occored");
die();
}else{
$Message .= "\n<br />mySQL error: ".mysql_error()."\n<br />";$Message .= "mySQL error code: ".mysql_errno()."\n<br />";$Message .= 'Date: '.date("l dS of F Y h:i:s A").'<br />';$title = "Database Error";
$error = "There appears to be an error with the <a href='{$this->Config['SiteAddress']}'>{$this->Config['SiteName']}</a> database.You can try to refresh the page by clicking <a href='javascript:window.location=window.location;'>here</a>, if thisdoes not fix the error, you can contact {$this->Config['ContactName']} by clicking <a href=\"mailto:{$this->Config['ContactEmail']}?subject=SQL+Error&message=".htmlspecialchars($Message, true)."\">here</a><br /><br /><b>Error Returned:</b><br /><div class='warnbox'><p class='small'>".$Message."</div>";print($error);
exit();
}//If !$Message
}//Error
}//Class DB
?>
Now, this might seem like a lot, but we are not going to touch this file, it is a class that I wrote to use for this kind of thing. The only thing you need to look at here is this:
if(IsInternal!=1){
die("Cannot access directly!");
}
Basically, what this is is checking to make sure we are calling this file from within our PHP program, and not just going to host/mySQL.php.
Now let's get to the code. First we will build a basic skeleton to house our little poll. We need to layout the Database, and decide what to call everything.
For now, let's just assume that we are going to use exactly the same layout that I used. For that, here is our SQL query:
CREATE TABLE `poll_answers` (
`ID` int(11) NOT NULL auto_increment,
`Votes` int(11) NOT NULL default '0',
`PollID` int(11) NOT NULL default '0',
`Answer` text NOT NULL,
PRIMARY KEY (`ID`)
) TYPE=MyISAM AUTO_INCREMENT ;
CREATE TABLE `poll_polls` (
`PollID` int(11) NOT NULL default '0',
`NumVotes` text NOT NULL,
`Question` text NOT NULL,
PRIMARY KEY (`PollID`)
) TYPE=MyISAM;
There, that'll make it easy, just load that up in phpMyAdmin or whatever you use to administer your database and run it.
Now, lets build the basic Framework for our poll. Save this as poll.php.
<?php
session_start();//Start a session to keep people from voting more then once within a certain amount of time
define("IsInternal", true);//Lets everything know we are calling the script from within our application. not directly
header("Cache-control: private"); // IE Fix.
require("config.php"); //Get our configuration
$Config = new Config; //Create a new config class
require($Config->DBDriver); //Get our Database Driver
$DB = new DB; //Create a new Database class
$DB->Config = $Config->DBConfig;
$DB->Connect();
/*Do Something */
$DB->CloseDB;
function BuildHTML($Step){
}
?>
Ok, this is all really basic stuff people, and if you read the comments, (the stuff behind the //'s) I think you will figure it out.
The first thing we need to do is get the information about what poll we are dealing with here, we use the handy little $_GET array to do this.
What we will be able to do is call our PHP script as poll.php?poll=1 and the var $_GET['poll'] will be assigned the value of 1.Right above our Connection lets add this: $ID = $_GET['poll']; now, right below the $DB->Connect add this:
$DB->Query("SELECT * FROM poll_polls WHERE PollID='".$ID."'");
While($Data = $DB->FetchRow()){
$TotalVotes = $Data['NumVotes'];
$Question = $Data['Question'];
}
$Answers = array();
$Count = 0;
$DB->Query("SELECT * FROM poll_answers WHERE PollID='".$ID."' ORDER BY ID");
while($Data = $DB->FetchRow()){
$Answers[$Count] = $Data['ID'].":".$Data['Answer'];
$Count += 1;
}
Ok, what is this? We are going out to our Database and telling it to give us all the polls with an ID of whatever our var $ID is assigned to. Then we are telling it to give us all the answers that have a PollID that is the same as our var $ID.
The poll question goes into a static var called $Question and the answers go into an array called $Answers (original eh?) Now lets add some more functionality to it. In our function BuildHTML, right where it starts add this: global $Answers, $Question, $Percent, $TotalVotes, $Count, $ID, $DB; all that does is lets our function have access to all the vars we put there. here is the completed function:
function BuildHTML($Step){global $Answers, $_SERVER, $Question, $Percent, $TotalVotes, $Count, $ID, $DB;
$URL0 = "http://".$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF']."?poll=".$ID;
if($_GET['src']=="jscript"){
$URL1 = $_SERVER['HTTP_REFERER'];
}else{
$URL1 = $URL0;
}
Switch($Step){
case 1:
$HTML = "<div class='poll'>".$Question."<br /><br /><form action='".$URL0."' method='post'>\n";$i = 0;
while($i!=$Count){
list($VoteID, $Answer) = split(":", $Answers[$i]);
$HTML .= "<input type='radio' name='vote' value='".$VoteID."' class='radiobutton' />".$Answer." <br />\n";$i++;
}
$HTML .="<input type='hidden' name='refer' value='".$URL1."' /><input type='hidden' name='PollID' value='".$ID."' /><input type='submit' name='submit' value='Submit' /></form></div>";break;
case 2:
$HTML = "<div class=poll>".$Question."<br /><br />";$DB->Query("SELECT * FROM poll_answers WHERE PollID='".$ID."' ORDER BY ID");
while($Data = $DB->FetchRow()){
$Votes = $Data['Votes'];
$Percent = $Votes * 100 / $TotalVotes;
$Percent = floor($Percent);
$Field = $Data['Answer'];
$HTML .= htmlspecialchars($Field);
$HTML .= ": <strong>".$Votes."</strong><br />\n";$HTML .= "<div style='background-color:'#D7D7D7';><div style='color:#000000; font-size:11px; text-align: right; background-color:#4795C3; width:".$Percent."%;'>".$Percent."%</div></div>\n";}
$HTML .= "<br />Total votes: <strong>".$TotalVotes."</strong></div>";
break;
}
if($_GET['src']=="jscript"){$JScript = array();
$JScript = explode("\n", $HTML);
for ($i = 0; $i<count($JScript); $i++){
print("document.write(\"$JScript[$i]\"); \n");
}//for
}else{
print($HTML);
}
}
The only thing weird here (that I think anyway) is the thing that says Switch($Step) and the thing that says explode("\n", $HTML). Ok, switch is like a specialized if else statement, and the explode function splits a string specified in the second var passed into an array at the first var passed. In this case it's "\n" which in PHP is a new line. We have just a very little bit of code left, just some checks and stuff like that. This goes right above the $DB->CloseDB; line:
if($_POST['submit']){
//grab vars
$Vote = $_POST['vote'];
$Refer = $_POST['refer'];
$PollID = $_POST['PollID'];
//update numbers
$DB->Query("UPDATE poll_polls SET NumVotes=NumVotes+1 WHERE PollID='".$PollID."'");
$DB->Query("UPDATE poll_answers SET Votes=Votes+1 WHERE ID='".$Vote."' AND PollID='".$PollID."'");
session_register('voted');//tell the sucker we have voted
$_SESSION['voted'] = array();
$_SESSION['voted'][$PollID] = true;
header("Location: $Refer");
}elseif ($_SESSION['voted'][$ID]){
//display results
BuildHTML(2);
}else{
//display the form!
BuildHTML(1);
}
That's it folks, easy pie if you know a little PHP, 94 lines of code to make a poll. Let's break this last part down.
First we check if the thing has been posted back to, if it has we grab the vars 'vote' 'refer' and 'pollid' we then run querys to the database to reflect the new vote and register a session, (kinda like cookies, 'cept server side) to make sure we can't vote again until it expires, (whatever is set in your hosts php.ini file) Then we use a (header("location:") to redirect the viewer to the site they where at, so it is almost like they never left.
If it's not a postback we check to see if the user has voted on this poll, and if he has we call BuildHTML(2); which builds the HTML to display the results if he hasn't the we call BuildHTML(1); which builds HTML to allow you to vote.
You can do something like this:
<script src="{Your site}\poll.php?poll={id}&src=jscript" />
To put the poll anywhere on your site.
I hope you find this guide useful, and if you have any comments or suggestions please tell me.
|