公子手把手教你写留言板程序

作者:公子 发布时间:March 6, 2011 分类:附庸风雅

网络上各种各样的PHP教程和各种各样的留言板都是铺天盖地的,战地为什么要自己写一个这样的PHP留言板教程呢?问的好啊!鼓掌。首先战地写这个PHP教程的目的不是为了做一个留言板,如果你需要一个留言板的话我建议你去Google搜索一下免费的、功能强大的、功能齐全的、 漂亮的到处都是。目的是:从一个简单的实际的案例出发,来让想学习PHP的兄弟姐妹们进入PHP的世界。需要说明的是,既然是实际的案例教程,各种各样的知识都会涉及到(以保证各位遇到更多的问题),阅读这个教程的时候你最好了解一点Html和 javascript的知识,因为在教程中将不作为重点来说。因为我们是PHP教程。

好了,现在说说我们将要设计的知识和这个留言板将要实现的功能:
功能需求:利 用PHP+Mysql数据库制作一个基本的留言板能够让客户进行留言,管理员可以对留言进行修改、删除、回复等操作。

在进行下面的学习之前,希望大家能够下载我编写的源码边看边学,这样能达到最好的效果。源码下载请点击这里。拿到源码请先看README文件

1.文件结构的功能的架设

为了制作一个留言板首先我们需要考虑好要创建什么东西。首先需要一个单独存放数据库信息的config.php文件,然后当然是index.php。当然还需要有表单数据处理的action.php文件,已经函数归类的function.php文件。哦,不要忘记了,留言板需要管理员登陆的,所以还要一个login.php文件。

也就是我我们需要创建5个文件,功能分别如下:

  • 1.index.php - 首页显示留言框和留言等信息的
  • 2.config.php - 记录数据库信息的
  • 3.action.php - 接受表单数据进行数据库处理的
  • 4.function.php - 函数归档文件
  • 5.login.php - 管理员登陆页面

2.需要掌握的PHP知识和常用函数

通过查看源码可以看出基本需要的几个函数分别是:ehco,if,while,switch,requireonce,header等。另外你还需要了解COOKIE和SESSION两个东东。下面我会一一为大家解释一下

1.PHP语句的写法

PHP 的语句以 <?php 开始,以 ?> 结束。您可以把 PHP 的脚本块放置在文档中的任何位置。当然,在支持简写的服务器上,您可以使用 来开始和结束脚本块。不过,为了达到最好的兼容性,我们推荐您使用标准形式 (<?php),而不是简写形式。实际操作中并不是一个<?php ?>包括所有的东西,而是运用了HTML和PHP混排的效果,即需要使用PHP语言的地方用,不需要的时候就不用。

2.PHP变量

PHP 中的变量变量用于存储值,比如数字、文本字符串或数组。一旦设置了某个变量,我们就可以在脚本中重复地使用它。PHP 中的所有变量都是以 $ 符号开始的。


3.PHP字符串

这个我就不多做介绍了,基本上和数学差不多。但大家要注意以下的是,PHP中%是取余的计算符号,在常量/变量前加!是表示非的意思,=是赋值的符号(即将等号右边的值赋给等号左边的东西)。而如果你想使用等于这个符号的话,必须使用 ==

4.echo书写

PHP输入文本的基本指令

5.if条件

当您编写代码时,您常常需要为不同的判断执行不同的动作,您可以在代码中使用条件语句来完成此任务。
if{} 语句
在条件成立时执行一块代码,否则跳过该语句
if...else 语句
在条件成立时执行一块代码,条件不成立时执行另一块代码
elseif 语句
与 if...else 配合使用,在若干条件之一成立时执行一个代码块

6.while循环

在您编写代码时,您经常需要让相同的代码块运行很多次。您可以在代码中使用循环语句来完成这个任务。while语句能够帮助你执行这个动作,只要指定的条件成立,while 语句将重复执行代码块。

7.switch选择

如果您希望有选择地执行若干代码块之一,请使用 Switch 语句。
工作原理:

  • 1.对表达式(通常是变量)进行一次计算
  • 2.把表达式的值与结构中 case 的值进行比较
  • 3.如果存在匹配,则执行与 case 关联的代码
  • 4.代码执行后,break 语句阻止代码跳入下一个 case 中继续执行
  • 5.如果没有 case 为真,则使用 default 语句

8.requireonce包含


通过requireonce语句,能够将另外的文件添加进当前文件中,对文件的引用非常有帮助

9.header信息

通过header函数,你可以在PHP中定义一些HTML页面中<head></head>提供的信息,例如本代码中就经常使用header进行跳转操作。

10.自定义函数

我们能够将我们经常需要用到得一大堆步骤打包成一个函数,方便自己的使用。例如数据库的操作等...

创建 PHP 函数:

  • 所有的函数都使用关键词 "function()" 来开始
  • 命名函数 - 函数的名称应该提示出它的功能。函数名称以字母或下划线开头。
  • 添加 "{" - 开口的花括号之后的部分是函数的代码。
  • 插入函数代码
  • 添加一个 "}" - 函数通过关闭花括号来结束。

3.PHP和数据库的基本交互

1.表单

程序的基本目的是通过PHP获取用户输入的留言信息,然后传递给数据库进行读取与编辑。但是这些信息是如何传递给数据库的呢,这就需要引用表单的概念。表单内获得的数据能够非常轻松的传递给各个地方。一个<form></form>即为一个表单,表单需要制定action和method两个属性,action属性是指表单获取到得数据要传递的终点站,而method的值是指定传输的方法,有GET和POST两种方法,GET是通过URL地址传输过去,而POST不是通过URL传说的。也就是说设置在URL中的值能够方便的通过GET方法来获取。表单内一般使用<input>输入框来让用户输入信息,input输入框必须要有name属性,通过name属性,表单才能调用该输入框的输入信息。如果你要知道更加详细的信息,可以看看这里

2.数据库的基本操作

想要对数据库进行操作,首先必须要连接(Connect)数据库。用户的留言是需要输入(Insert)进数据库的,管理员删掉留言是对数据库进行删除(DELETE)操作的。操作完成之后我们必须关闭(CLOSE)与数据库的连接。每次对数据库进行操作,我们都必须进行一次连接与断开连接的操作,为了方便自己,可以把这一个操作写成自定义函数的形式。(本示例中包装成了sqlquery函数,在function.php第3行)

4.开始写留言板程序

1.创建数据库

这里我以PHPmyadmin为例,进入到如图所示 的界面然后输入如下代码并点击执行。这样数据库就建立好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</h2>
<h2>-- 数据库: <code>guestbook</code></h2>
<p>CREATE DATABASE <code>guestbook</code> DEFAULT CHARACTER SET latin1 COLLATE latin1<em>swedish</em>ci;
USE <code>guestbook</code>;
-- 如果是在已经存在的表中建立,则将上面的代码去除后执行即可</p>
<hr />
<h2>-- 需要建立的表有entry,user,如果有重名的表,修改相关代码执行即可</h2>
<h2>-- 表的结构 <code>entry</code></h2>
<p>CREATE TABLE IF NOT EXISTS <code>entry</code> (
<code>id</code> int(10) NOT NULL AUTO<em>INCREMENT,
<code>username</code> varchar(255) CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
<code>content</code> mediumtext CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
<code>time</code> int(10) NOT NULL,
<code>email</code> varchar(255) CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
<code>website</code> varchar(255) CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
<code>agent</code> varchar(255) CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
<code>ip</code> varchar(15) CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
<code>geo</code> varchar(255) CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
PRIMARY KEY (<code>id</code>)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO</em>INCREMENT=1 ;</p>
<p>--</p>
<h2>-- 表的结构 <code>user</code></h2>
<p>CREATE TABLE IF NOT EXISTS <code>user</code> (
<code>id</code> int(10) NOT NULL AUTO<em>INCREMENT,
<code>username</code> varchar(255) CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
<code>password</code> varchar(255) CHARACTER SET utf8 COLLATE utf8</em>unicode<em>ci NOT NULL,
PRIMARY KEY (<code>id</code>)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO</em>INCREMENT=2 ;</p>
<p>--</p>
<h2>-- 转存表中的数据 <code>user</code></h2>
<p>INSERT INTO <code>user</code> (<code>id</code>, <code>username</code>, <code>password</code>) VALUES
(1, 'admin', '21232f297a57a5a743894a0e4a801fc3');

2.用户数据的提交和写入数据库

上面说了,数据的交互我们需要用到表单,所以要新建立一个表单,代码如下:

1
2
3
4
5
6
7
8
9
10
<form method="POST" action="action.php?act=post">
<?php if (!$_SESSION['login']) { ?>
昵称:<input name="username" id="username" class="username" type="text" value="<?php echo $_COOKIE['gbook_name']; ?>">
邮箱:<input name="email" id="email" class="email" type="text"value="<?php echo $_COOKIE['gbook_email']; ?>">
网站:<input name="website" id="website" class="website" type="text" value="<?php echo $_COOKIE['gbook_website']; ?>"></p>
<p><textarea name="content" id="content" class="content" rows="5"></textarea>
<input type="submit" value="确认">
<span style="font-size:12px;display:block;color:#CCC;float:right;">你可以使用的标签有:&lt;a&gt;,&lt;img&gt;,&lt;p&gt;,&lt;br&gt;,&lt;b&gt;</span>
</form>

如代码所示,如上我们就能够通过$POST['username'],$POST['email'],$POST['website'],$POST['content']分别获取用户的昵称,邮箱和网址已经留言内容等信息。这些信息的接受文件是action.php,那么我们需要在action.php中写入数据库的相关操作。(实例代码中将许多表单中的操作放到一个文件中了,为了代码的方便,所以添加了switch选择函数,而选择的对象则是通过GET方法从URL中获取的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
if (!$<em>SESSION['login']) {//判断用户是否登录,如果没登陆执行以下操作
$username = $</em>POST['username'];//赋值
setcookie('gbook<em>name',$username,time()+ 604800);//设置COOKIE
$email = $</em>POST['email'];
setcookie('gbook<em>email',$email,time()+ 604800);
$website = $</em>POST['website'];
setcookie('gbook<em>website',$website,time()+ 604800);
} else {//登录的话执行以下操作
$user = sql</em>query ('SELECT * FROM user WHERE username = "admin"');//读取用户数据
$user = mysql<em>fetch</em>object($user);//对取得的数据进行格式化
$username = $user -> nickname;//赋值管理员昵称
$email = $user -> email;
$website = $user -> url;
}
$content = $<em>POST['content'];
$ip = getip();//通过getip函数获取用户IP
$geo = user</em>ip($ip);//通过user<em>ip函数对IP地址进行解析,得到详细地质
if ($geo = "") {
$geo = "火星";//如果没IP或解析不到则显示为火星
}
$agent = $</em>SERVER[HTTP<em>USER</em>AGENT];//记录使用者的操作系统信息
if ($username !=="" &amp;&amp; $content !== "" ) {//如果昵称和留言内容都不为空则执行以下内容
$post<em>time = time();//获取时间
$content = strip</em>tags($content,'<br><p></p><img><a></a><b></b>');//对留言内容进行格式化
$insert<em>sql = "INSERT INTO entry (id, username, content, time, email, website, agent, ip, geo) VALUES ('','$username','$content','$post</em>time','$email','$website','$agent','$ip','$geo')";
sql<em>query($insert</em>sql);//将留言内容写入数据库
header('Location:index.php');//跳转回首页
} else {//如果昵称和留言内容二者有一个为空则执行以下语句
echo "<script>alert('昵称和留言内容是必须要填写的!');</script>";
}

我为这段代码进行了详细的解释,大家应该都能看的懂了。这里需要注意的是读取出来的SQL信息首先都必须对其进行格式化,可以选择的格式化函数有mysqlfetchobject,mysqlfetcharray等,这里选择了第一个。格式化后的信息就可以通过“信息 -> 字段名”的方式来获取相应字段的内容。

3.显示留言内容

通过对entry表进行SELECT读取操作显示最近的留言,整体的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<ul class="entry">
<?php
$entrys = get_entry_by_page($perpage);//通过自定义了函数来根据页面来显示内容,达到分页效果(这个函数在后面会讲)
while ($entry = mysql_fetch_object($entrys)) {//while循环执行读取格式化后的日志工作
?>
<li id="entry">
<span class="avatar">
<img src="<?php echo getavatar($entry -> email);/*根据留言者的邮箱获取他的Gravatar头像*/ ?>" alt="<?php echo $entry -> username; ?>">
</span>
<span class="top">
<span class="username">
<a href="<?php echo $entry -> website; ?>" target="_blank" alt="<?php echo $entry -> username; ?>"><?php echo $entry -> username;?></a>
</span>
<span class="information">
<span class="geo">来自<?php echo $entry -> geo; ?></span>
<span class="agent"><?php echo user_agent($entry -> agent); ?></span>
</span>
</span>
<span class="content"><?php echo nl2br($entry -> content);/*nl2br是将换行变成<br>的函数,不需要太多了解*/ ?></span>
<span class="time">发表于<?php echo time_past($entry -> time);/*通过自定义函数对Unix时间戳进行格式化并得到距离现在的时间*/ ?></span>
<span class="rep"><a href="#" onclick="inser('@<?php echo $entry -> username; ?>&nbsp;');return false;">[回]</a>
<?php if ($_SESSION['login']) { /*如果登录则执行以下代码*/?>
<span class="del"><a href="action.php?act=del&id=<?php echo $entry -> id; ?>">[删]</a></span>
<?php } ?>
</li>
<?php } ?>
</ul>

通过上一小节的学习,我想大家对上面这段代码应该基本上能懂了,我就不多做解释了。

5.分页效果的制作

其实分页就是考察你的计算能力,假如你每页显示10条内容,则你第i页显示的消息起始数为第[(i-1)*10+1]条,而第i页我们可以利用GET方法从URL地址中获取。通过ORDER BY 能够对数据进行顺序排列,而ORDER BY DESC能够对数据进行倒序排列。再添加上LIMIT a,b就可以自定义从数据的第a条开始取,一直取b条出来。创建成自定义函数之后就变成了

1
2
3
4
5
6
7
8
9
function get_entry_by_page($perpage) {
if ($_GET['page'] == "") {//设置当前页的默认值为1
$_GET['page'] = 1;<br />
}
$page = $_GET['page'];
$start_entry = ($page - 1) * $perpage;//$prepage为你设置的每页显示的条数
$entrys = sql_query('SELECT * FROM entry ORDER BY time DESC LIMIT ' . $start_entry . ', ' . $perpage);
return $entrys;<br />
}

除了做内容的分页,我们还需要做一个翻页的按钮才行,这个也是基本的计算问题,你们可以尝试的去理解一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function pages($perpage) {
$count = sql_query("SELECT COUNT(id) AS total FROM entry");
$count = mysql_fetch_object($count);
$count = $count -> total;//获取总条数
if ($count%$perpage == 0) {
$page_total = intval($count/$perpage);<br />
} else {
$page_total = intval($count/$perpage) + 1;<br />
}//获取总页数
if ($_GET['page'] == "") {
$_GET['page'] = 1;<br />
}
$page_class = 'page';
echo '<span class="pages">';
if ($_GET['page'] != 1) {
$pre_page = $_GET['page'] - 1;
echo '<span class="' . $page_class . '"><a href="index.php?page=' . $pre_page . '">&laquo;上一页</a></span>';<br />
}
if ($page_total &lt;= 5 ) {
for ($i=1;$i &lt;= $page_total;$i++) {
echo '<span class="' . $page_class . '"><a href="index.php?page=' . $i . '">' . $i . '</a></span>';<br />
}<br />
} else {
for ($i=1;$i &lt;= 5;$i++) {
echo '<span class="' . $page_class . '"><a href="index.php?page=' . $i . '">' . $i . '</a></span>';<br />
}<br />
echo "...";
echo '<span class="' . $page_class . '"><a href="index.php?page=' . $page_total . '">' . $page_total . '</a></span>';<br />
}
if ($_GET['page'] != $page_total ) {
$next_page = $_GET['page'] + 1;
echo '<span class="' . $page_class . '"><a href="index.php?page=' . $next_page . '">下一页&raquo;</a></span>';
}
echo '</span>';
}

6.管理员的登陆

对这个功能编写前,你们必须了解SESSION的相关知识,如果不知道请点这里我们对用户提交过来的用户名和密码进行校验,如果匹配就把$_SESSION['login']赋值为真(true),否则就告诉用户登录失败。密码是采用md5加密方法存储到数据库里面的。详细代码可以参看login.php文件已经action.php文件。

5.总结

本篇文章知识草草的从我的角度上编写了一个简单的教程,对某些简单的问题可能讲的过于繁琐,当然可能对某些复杂的问题避而不讲。所以大家在遇到不懂的问题的时候,希望能够善于利用搜索引擎来帮助自己更好的理解这篇文章。按照步骤来基本上不会出什么错,如果有出错了,首先一定要记得检查一下是不是你的书写有问题,是不是少了一个s,或者是少了一个;等等。

本文章中的专业性知识的讲解部分是引用自W3school。W3school是一个不错的网络入门学习网站,推荐大家去看一看。

Emlog碎语转换到PageCookery

作者:公子 发布时间:February 26, 2011 分类:附庸风雅

N久之前有某位同学给我发邮件让我帮忙写一个emlog碎语转PageCookery的数据库转换程序。虽然没有什么技术,但感觉这东西还是有些思路的,就接下来了。在卜卜口の君的帮助下,也算是有模有样的写出来了。并且拿了一个emlog的碎语数据库做过测试,因为他的内容多且杂,应该能代表广大群众的了。所以特地分享出来,希望能帮助一些同学。

将下列代码保存成covertopc.php,然后上传到emlog程序的根目录访问即可得到转换代码。本来想写成下载文件下载成SQL文件然后让用户自己导入的。我想直接代码也不还是PHPMYADMIN,于是就没多做操作了。虽然我做了测试,但不代表一定没有问题,欢迎使用中有问题的同学和我交流,最后说明问题的时候能发一份你的碎语数据库文件到我的邮箱里头。我的邮箱是i#imnerd.org

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<html>
<head>
<title>Emlog碎语转PageCookery程序 </title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
textarea {width:100%;height:200px;}
form {width:400px;}
button {float:right;}
#footer {width:100%;text-align:center;position:fixed;bottom:0px;}
</style>
</head>
<body>
&lt;?php
require<em>once 'config.php'; //连接数据库<br />
function mysql</em>run($sqlcon){<br />
$con=mysql<em>connect(DB</em>HOST, DB<em>USER,DB</em>PASSWD);
mysql<em>select</em>db(DB<em>NAME);
mysql</em>query("SET NAMES 'utf8'");
$result = mysql<em>query($sqlcon);
mysql</em>close($con);
return $result;
}</p>
<p>?></p>
<p>复制下列代码并在phpMyadmin中执行即可<a href="http://img1.dnschina.net/files/68/insert_into_sql.png" target="_blank" style="font-size:12px;">不懂请看图</a></p>
<p><textarea></p>
<p>&lt;?php</p>
<p>$content = mysql<em>run('SELECT * FROM ' . DB</em>PREFIX . 'twitter');</p>
<p>while($entry=mysql<em>fetch</em>object($content)){
echo "INSERT INTO <code>entry</code> VALUES ";
echo "('',1,'" . htmlspecialchars( str<em>replace('&#92;','',$entry -> content) , ENT</em>QUOTES ) . "'," . $entry -> date . ",'Emlog'," . $entry -> author . ");";
}
?></p>
<p><?php
$re = mysql_run('SELECT * FROM ' . DB_PREFIX . 'reply');
while($reply =mysql_fetch_object($re)){
echo "INSERT INTO `reply` VALUES";
echo "(''," . $reply -> tid .",'Great Fire Wall', '" . $reply -> ip . "','" . $reply -> content . "'," . $reply -> date . ",'0','" . $reply -> name . "');";
}
?>
</textarea>
<p style="margin-top:15px;color:#AAA;">
友情提示:<br>
1.请确定你是在PageCookery的表中执行代码,并确保PageCookery已经安装,即存在entry和reply两个表。<br>
2.部分对数据库架构进行过变动的用户可能会导入失败,请修改相关代码后再进行导入。<br>
3.导入前请将原数据库进行备份,以免发生意外损失。
</p>
<div id="footer">Powered By <a href="http://imnerd.org">怡红公子</a> | 欢迎报告 <a href="mailto:i@imnerd.org">BUG</a></div>
<body>
</html>