如何设计和创建 PHP 驱动的投票

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费信用额度!

投票很有趣!它们可以帮助吸引您网站的读者,并为您和投票者提供有价值的信息。让我们一起从头开始构建一个投票。从 Photoshop 设计到为其提供支持的 PHP/MySQL,我们将逐步完成所有步骤。以下是我们将构建的内容

实时演示已不再在线,但您可以 下载此演示的所有文件的 .zip 文件

1. 在 Photoshop 中设计背景

创建一个全新的 Photoshop 文档。在我的文档中,我已将背景填充为深蓝色(#233743),并将其大小设置为 700x700px。

然后在背景图层之上创建一个全新的图层(按图层调色板中的小页面图标)。选择渐变工具(油漆桶工具的子工具)。确保渐变工具设置为“前景色到透明”、“径向”和“完全不透明”,如下所示

在我的文档中,我使用了稍浅的蓝色(#364c5a),并从顶部中间附近拖出一个渐变。渐变可以“超出”顶部,但请确保它不会超出任一侧或底部。这里的想法是,我们将将其居中在一个匹配蓝色的背景上,因此我们不希望渐变突然结束。我们将其单独放在一个图层上的原因是,我们可以调整它而无需重新进行操作。

现在让我们在顶部添加有趣的“投票!”文本。在这里,我使用了 Agenda Black 字体(我的新宠之一),颜色为更浅的蓝色(#e3f1fa)。我对其进行了自由变换(Command-T)以使其稍微旋转,然后在图层样式中为其添加了轻微的投影。

现在图形已准备好保存。您可以从文件菜单中“存储为 Web 所用格式和设备”。使用高质量 JPG 设置(最适合具有渐变的大型图像)。将文件命名为“page-bg.jpg”,并将其保存到您将用于此项目的目录内的“images”文件夹中。

2. 构建页面结构

在我们的案例中,投票只是一个非常简单的表单。基本上是一系列单选按钮输入和一个提交按钮。以下是整个 HTML 标记的外观

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Poll</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<fieldset>
	<legend>What is your JavaScript library of choice?</legend>
	<form action="<?php echo $editFormAction; ?>" id="form1" name="form1" method="POST">
		<label>
			<input type="radio" name="Poll" value="mootools" id="Poll_0" />
			Mootools
		 </label>
		<label>
			<input type="radio" name="Poll" value="prototype" id="Poll_1" />
			Prototype
		</label>
		<label>
			<input type="radio" name="Poll" value="jquery" id="Poll_2" />
			jQuery
		</label>
		<label>
			<input type="radio" name="Poll" value="spry" id="Poll_3" />
			Spry
		</label>
		<label>
			<input type="radio" name="Poll" value="other" id="Poll_4" />
			Other
		</label>
		<input type="submit" name="submit" id="submit" value="Vote" />
		<input type="hidden" name="id" value="form1" />
		<input type="hidden" name="MM_insert" value="form1" />
	</form>
</fieldset>
</body>
</html>

这里需要注意的几点。我将表单放在了一个 fieldset 中。这里没有功能相关的内容,我只是喜欢 fieldset/legend 组合的外观,并且它为我们提供了一些 CSS 样式的挂钩。还要注意输入是如何位于 label 元素内的。这允许用户单击文字以及单选按钮来选择它,这很好。还要注意表单操作中的 PHP 代码片段,我们稍后会讲到。

以下是 CSS

* { 
	margin: 0; 
	padding: 0; 
}
body { 
	font-size: 62.5%; 
	font-family: Georgia, serif;
	background: url(images/page-bg.jpg) top center no-repeat #233743; 
}
h6 {
	font-size: 1.4em;
	margin-bottom: 15px;
}
a { color: white; }
label, li {
	display: block;
	padding: 5px;
	font-size: 1.4em;
	color: #e3f1fa;
}
fieldset {
	margin: 115px auto;
	width: 400px;
	padding: 8px 15px 15px 15px;
	border: 1px solid white;
	display: block; /* IE 7 Requires This */
	}
	legend {
		padding: 4px 6px 4px 6px;
		border: 1px solid white;
		font-size: 2.0em;
		color: #e3f1fa;
		font-style: italic;
	}
ul { list-style: none; margin-bottom: 15px;}
.results-bar {
	padding: 10px;
	color: white;
	background: url(images/result-bar-bg.png) left center;
	white-space: nowrap;
}
span.total-votes {
	font-size: 2.6em;
}

请注意底部针对我们标记中尚未包含的内容的样式,这些样式是针对我们稍后将要介绍的结果页面。

3. 创建一个数据库来存储结果

大多数托管套餐允许您在服务器上创建数据库。如果您还不知道如何操作,可能需要联系他们或搜索其帮助区域以了解如何添加新数据库。

CSS-Tricks 位于 Media Temple,因此域管理员区域中有一个方便的小工具可用于创建新数据库

确保这是一个 MySQL 数据库。您需要了解的四件事是主机名、数据库用户名、数据库“密码”和数据库名称。

现在,您需要在为此项目启动的目录中创建一个名为“conn_vote.php”的新文件。我已将其放在名为“Connections”的子文件夹中。以下是 PHP

<?php
# FileName="Connection_php_mysql.htm"
# Type="MYSQL"
# HTTP="true"
$hostname_conn_vote = "localhost";
$database_conn_vote = "your-database-name";
$username_conn_vote = "your-database-username";
$password_conn_vote = "your-database-password";
//$conn_vote = mysql_pconnect($hostname_conn_vote, $username_conn_vote, $password_conn_vote) or trigger_error(mysql_error(),E_USER_ERROR);
$conn_vote = mysql_connect($hostname_conn_vote, $username_conn_vote, $password_conn_vote) or die('Can\'t create connection: '.mysql_error());
mysql_select_db($database_conn_vote, $conn_vote) or die('Can\'t access specified db: '.mysql_error());
?>

请注意上面以粗体显示的四行,它们是前面提到的您需要了解的四件事的四个变量。您的主机很可能是 localhost,但并非总是如此。以我为例,在 Media Temple 中,它类似于:internal-db.s12345.gridserver.com

您的全新空数据库将需要一个表结构和一些假数据才能开始使用。以下是一些您可以运行的 SQL 代码来完成此操作

-- 
-- Table structure for table `poll`
-- 
CREATE TABLE `poll` (
  `id` int(3) NOT NULL auto_increment,
  `question` varchar(200) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=43 ;
-- 
-- Dumping fake data for table `poll`
-- 
INSERT INTO `poll` VALUES (42, 'jquery');
INSERT INTO `poll` VALUES (41, 'mootools');
INSERT INTO `poll` VALUES (40, 'other');
INSERT INTO `poll` VALUES (39, 'mootools');
INSERT INTO `poll` VALUES (38, 'jquery');
INSERT INTO `poll` VALUES (37, 'mootools');
INSERT INTO `poll` VALUES (36, 'spry');
INSERT INTO `poll` VALUES (35, 'jquery');
INSERT INTO `poll` VALUES (21, 'mootools');
INSERT INTO `poll` VALUES (22, 'other');
INSERT INTO `poll` VALUES (23, 'mootools');
INSERT INTO `poll` VALUES (24, 'mootools');
INSERT INTO `poll` VALUES (25, 'prototype');
INSERT INTO `poll` VALUES (26, 'other');
INSERT INTO `poll` VALUES (27, 'mootools');
INSERT INTO `poll` VALUES (28, 'spry');
INSERT INTO `poll` VALUES (29, 'jquery');
INSERT INTO `poll` VALUES (30, 'mootools');
INSERT INTO `poll` VALUES (31, 'prototype');
INSERT INTO `poll` VALUES (32, 'mootools');
INSERT INTO `poll` VALUES (33, 'mootools');
INSERT INTO `poll` VALUES (34, 'mootools');

大多数主机还允许您访问 phpMyAdmin 来运行此类代码。**请确保**您位于新数据库中,然后您可以粘贴该 SQL 代码并运行它。

4. 使其与 PHP 协同工作

现在,我们已准备好使用一些 PHP 编码技巧来使这一切正常工作。我不能假装理解所有这些,但其要点是,它将获取您选择的选项,将其转换为易读且安全的字符串值,并将其作为新条目保存在数据库中的该表中。

非常感谢 Jonathan Fean 为此提供支持的 PHP 代码,以及 David Walsh 帮助我解决了一些问题并使其在我的服务器上运行。

将此 PHP 代码插入 poll.php 文件的顶部(甚至在 DOCTYPE 之前)

<?php require_once('Connections/conn_vote.php'); ?>
<?php
if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
  $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;

  $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

  switch ($theType) {
    case "text":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;    
    case "long":
    case "int":
      $theValue = ($theValue != "") ? intval($theValue) : "NULL";
      break;
    case "double":
      $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL";
      break;
    case "date":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;
    case "defined":
      $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
      break;
  }
  return $theValue;
}
}

$editFormAction = $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
  $editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
}

if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
  $insertSQL = sprintf("INSERT INTO poll (id, question) VALUES (%s, %s)",
                       GetSQLValueString($_POST['id'], "int"),
                       GetSQLValueString($_POST['Poll'], "text"));

  mysql_select_db($database_conn_vote, $conn_vote);
  $Result1 = mysql_query($insertSQL, $conn_vote) or die(mysql_error());

  $insertGoTo = "results.php";
  if (isset($_SERVER['QUERY_STRING'])) {
    $insertGoTo .= (strpos($insertGoTo, '?')) ? "&" : "?";
    $insertGoTo .= $_SERVER['QUERY_STRING'];
  }
  header(sprintf("Location: %s", $insertGoTo));
}

$colname_rs_vote = "-1";
if (isset($_GET['recordID'])) {
  $colname_rs_vote = $_GET['recordID'];
}
mysql_select_db($database_conn_vote, $conn_vote);
$query_rs_vote = sprintf("SELECT * FROM poll WHERE id = %s", GetSQLValueString($colname_rs_vote, "int"));
$rs_vote = mysql_query($query_rs_vote, $conn_vote) or die(mysql_error());
$row_rs_vote = mysql_fetch_assoc($rs_vote);
$totalRows_rs_vote = mysql_num_rows($rs_vote);
?>

以及 poll.php 文件末尾的此 PHP 代码(甚至在 <html> 之后)

<?php
  mysql_free_result($rs_vote);
?>

5. 创建结果页面

因此,我们的投票已启动并运行,并成功收集了投票,但结果页面才是真正的回报!这不仅是有趣的部分,而且我们的 PHP 函数在您按下投票按钮后会自动重定向到“results.php”页面,因此我们必须构建一个 =)

这次,我将把所有标记和 PHP 代码一起放在一个大块中提供给您

<?php require_once('Connections/conn_vote.php'); ?>
<?php
if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
  $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;

  $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

  switch ($theType) {
    case "text":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;    
    case "long":
    case "int":
      $theValue = ($theValue != "") ? intval($theValue) : "NULL";
      break;
    case "double":
      $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL";
      break;
    case "date":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;
    case "defined":
      $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
      break;
  }
  return $theValue;
}
}

mysql_select_db($database_conn_vote, $conn_vote);
$query_rs_vote = "SELECT * FROM poll";
$rs_vote = mysql_query($query_rs_vote, $conn_vote) or die(mysql_error());
$row_rs_vote = mysql_fetch_assoc($rs_vote);
$totalRows_rs_vote = mysql_num_rows($rs_vote);

$resultQuestion1 = mysql_query("SELECT * FROM poll WHERE question='mootools'");
$num_rowsQuestion1 = mysql_num_rows($resultQuestion1);

$resultQuestion2 = mysql_query("SELECT * FROM poll WHERE question='prototype'");
$num_rowsQuestion2 = mysql_num_rows($resultQuestion2);

$resultQuestion3 = mysql_query("SELECT * FROM poll WHERE question='jquery'");
$num_rowsQuestion3 = mysql_num_rows($resultQuestion3);

$resultQuestion4 = mysql_query("SELECT * FROM poll WHERE question='spry'");
$num_rowsQuestion4 = mysql_num_rows($resultQuestion4);

$resultQuestion5 = mysql_query("SELECT * FROM poll WHERE question='other'");
$num_rowsQuestion5 = mysql_num_rows($resultQuestion5);

$percentQuestion1 = ($num_rowsQuestion1 / $totalRows_rs_vote)*100;
$percentQuestion2 = ($num_rowsQuestion2 / $totalRows_rs_vote)*100;
$percentQuestion3 = ($num_rowsQuestion3 / $totalRows_rs_vote)*100;
$percentQuestion4 = ($num_rowsQuestion4 / $totalRows_rs_vote)*100;
$percentQuestion5 = ($num_rowsQuestion5 / $totalRows_rs_vote)*100;

?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Results</title>
	<link href="style.css" rel="stylesheet" type="text/css" />
</head>

<body>
	<fieldset>
	
		<legend>Results</legend>
		
		<ul>
			<li>
				<?php echo $num_rowsQuestion1 ?> Mootools
				<br />
				<div class="results-bar" style="width: <?php echo round($percentQuestion1,2); ?>%;">
					 <?php echo round($percentQuestion1,2); ?>%
				</div>
			</li>
			
			<li>
				<?php echo $num_rowsQuestion2 ?> Prototype
				<div class="results-bar" style="width: <?php echo round($percentQuestion2,2); ?>%;">
					 <?php echo round($percentQuestion2,2); ?>%
				</div>
			</li>
		
			<li>
				<?php echo $num_rowsQuestion3 ?> jQuery
				<div class="results-bar" style="width: <?php echo round($percentQuestion3,2); ?>%;">
					 <?php echo round($percentQuestion3,2); ?>%
				</div>
			</li>
		
			<li>
				<?php echo $num_rowsQuestion4 ?> Spry
				<div class="results-bar" style="width: <?php echo round($percentQuestion4,2); ?>%;">
					 <?php echo round($percentQuestion4,2); ?>%
				</div>
			</li>
		
			<li>
				<?php echo $num_rowsQuestion5 ?> Other
				<div class="results-bar" style="width: <?php echo round($percentQuestion5,2); ?>%;">
					 <?php echo round($percentQuestion5,2); ?>%
				</div>
			</li>
		</ul>
	
		<h6>Total votes: <?php echo $totalRows_rs_vote ?></h6>
		
		Back to Voting
	
	</fieldset>
	
</body>
</html>

<?php
  mysql_free_result($rs_vote);
?>

请注意,PHP 中进行了一些小的计算,这些计算将计算每个投票选项的总投票百分比。这不仅是有用的信息,而且我们可以使用该百分比来设置条形的宽度,从而为我们的结果添加一些视觉效果。每个投票选项都有自己的列表项,其中显示该项目的总投票数以及“results-bar”,其宽度通过将内联宽度值设置为计算出的百分比来确定。在我们的 CSS 中,我们已经使用细微的图案化背景图像对该 div 进行了样式设置。

实时演示已不再在线,但您可以 下载此演示的所有文件的 .zip 文件

(请记住:这需要运行 PHP 和 MySQL 数据库的服务器,因此您需要按照上述步骤才能使其在您自己的服务器上运行。包含 Photoshop 文件。)