14.5 博文管理模块设计
对于博客系统来说,文章管理是最基本的功能,但同时也是最复杂的一个功能。本系统的博文管理模块包括“添加博客文章”、“查找博客文章”、“管理我的博客”、“发表评论”、“删除博文”和“删除评论”6大功能。其中,普通用户只能删除自己的博文及对博文的评论,只有管理员才有权删除任何一篇文章及回复。
14.5.1 博文管理模块技术分析
想使用博文管理模块,用户必先登录,匿名用户无法使用博文管理模块的功能;要想删除博文和评论,前提是当前用户必须拥有管理员权限,或者是博文或评论的拥有者,否则不会显示删除功能。这两方面的控制都需要Session的配合,本节介绍Session的应用及常见的问题处理。Session的中文译名为“会话”,是指用户从进入网站开始,直到离开网站这段时间内,所有网页共同使用的公共变量的存储机制。Session比Cookie更有优势:Session是存储在服务器端的,不易被伪造;Session的存储没有长度限制;Session的控制更容易等。但大多数初学者在使用PHP中的Session时,经常出现一些莫名其妙的错误,而又不知道如何去解决。其实,大多数的错误的原因是对Session的配置不了解造成的,在php.ini中对Session的配置如表14-2所示。
配置选项 | 说明 |
session.save_path = c:/temp | 保存Session变量的目录,在Linux/UNIX下为/tmp |
session.ues_cookies = 1 | 是否使用Cookie |
session.name = PHPSESSID | 表示会话ID |
session.auto_start = 0 | 是否自动启用Session,当为1时,在每页中就不必调用Session_satrt()函数了 |
session.cookie_lifetime = 0 | 设定Cookie送到浏览器后的保存时间,单位为s。默认值为0,表示直到浏览器关闭 |
session.cookie_path = / | Cookie有效路径 |
session.cookie_domain = | 有效域名 |
session.serialize_handler = php | 定义串行化数据的标识,本功能只有WDDX模块或PHP内部使用,默认值为PHP |
session.gc_probability = 1 | 设定每次临时文件开始处理的处理概率。默认值为1 |
session.gc_maxlifetime = 1440 | 设定保存Session的临时文件被清除前的存活秒数 |
session.referer_check = | 决定参照到客户端的Session代码是否要删除。有时出于安全或其他考虑,会设定不删除。默认值为0 |
session.cache_limiter = nocache | 设定Session缓冲限制 |
session.cache_expire = 180 | 文档有效期,单位为min |
session.save_handler = files | 用于保存Session变量,默认情况下用文件 |
对于初学者来讲,Session在php.ini中是不需要改动的,因为安装时会根据操作系统自行做出适当的调整。只将少数的几项,如Session存活周期(session.cookie_lifetime = 0)、自动开启Session(session.auto_start)等稍加改动即可。PHP主要是通过会话(Session)处理函数来对Session进行控制和使用的。常用的处理函数如表14-3所示。
函数 | 函数说明 |
session_start(); | 开启Session或返回已经存在的Session |
$_SESSION['name'] = value; | 注册一个Session变量 |
session_id() | 设定或取得当前的Session_id值 |
isset($_SESSION['name]) | 检测指定的Session值是否存在。isset不只可以检测Session,还可以检测其他类型,如isset($_POST['name'])、isset($_GET['name'])等 |
session_regenerate_id() | 更改Session_id的值 |
session_name() | 返回或改变当前Session的name |
unset($_SESSION['name']) | 删除名为name的Session |
session_destroy() | 结束当前会话,删除所有Session |
注意:
(1)如需改变当前Session的name属性值,必须在session()之前调用session_name()函数,而且session_name不能全部是数字,否则会不停地生成新的session_id。
(2)不能使用unset($_SESSION)语句,这样将禁止整个会话的功能。使用Session时要注意以下问题。
①将session_start放到第1行。
这种情况是新手最容易犯的错误。产生的错误代码为:
Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent…
其原因就是在使用session_start()之前,就有HTML代码输出了。注意空行或类似echo语句的输出都被作为HTML的输出。
②使用Session之前,要先写session_start()。
在使用Session之前都能先调用session_start()函数,但对于session_destroy()函数却经常忽略。session_destroy()虽然是结束当前会话并删除所有Session,但在删除之前,也要先开启Session支持才可以,不然会产生这样的错误代码:session_destroy()[function.session-destroy]: Trying to destroy uninitialized session in…
所以,凡是在使用Session或Session函数的页面中,需要加上session_start()这句话。
③删除所有Session。
如果想删除所有Session,但又不想结束当前会话,用unset一个一个删除实在是太麻烦了,最简单的办法就是将一个空数组赋给$_SESSION,如$_SESSION = array()。
14.5.2 添加博文的实现过程
添加博文模块主要操作表t_article中的数据。用户登录后,系统会直接进入到文章添加页(file.php),也可以通过单击“博文管理”|“添加博客文章”回到file.php页。博文添加页面的运行结果如图14-13所示。
添加博文页为一个发布表单,包括博文主题、博文编辑、博文内容等元素。部分表单元素如表14-4所示。
用户填写完博文主题和博文内容后,单击“发表”按钮,系统将跳转到处理页(check_file.php)进行数据处理。在处理页中,根据传过来的博文标题、博文作者和博文内容等数据形成insert语句,并通过执行insert语句保存在数据库的t_article表中。如果添加信息成功,系统返回到本页,可继续执行添加操作;如果添加失败,则返回到上一步。关键实现代码如下。
<html> <head></head> <body> <?php session_start(); include "Conn/conn.php"; //echo $_POST["btn_tj"]; if($_POST["btn_tj"]<>""){ $title=$_POST[txt_title]; $author=$_SESSION[username]; $content=$_POST[file]; $now=date("Y-m-d H:i:s"); $sql="Insert Into tb_article (title,content,author,now) Values ('$title','$content','$author','$now')"; $result=mysql_query($sql); if($result){ echo "<script>alert('恭喜您,你的文章发表成功!!!');window.location. href='file.php';</script>"; } else{ echo "<script>alert('对不起,添加操作失败!!!');window.location. href='file.php';</script>"; } } ?> </body> <html>
14.5.3 博文列表的实现过程
单击“博文管理”|“我的博文”,将显示用户发表过的博文列表。博文列表页面(myfiles.php)的运行结果如图14-14所示。
博文列表页面使用了分页技术与do…while循环语句来输出博文的各标题,数据从表t_article中读出。程序关键代码如下。
<?php
session_start();
include "Conn/conn.php";
include "check_login.php";
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<link href="CSS/style.css" rel="stylesheet">
<title>我的文章</title>
<style type="text/css">
<!--
.style1 {color: #FF0000}
-->
</style>
</head>
<script src=" JS/menu.JS"></script>
<script src=" JS/UBBCode.JS"></script>
<script language="javascript">
function check(){
if(myform.txt_title.value==""){
alert("博客主题名称不允许为空!");myform.txt_title.focus();return
false;
}
if(myform.file.value==""){
alert("文章内容不允许为空!");myform.file.focus();return false;
}
}
</script>
<body >
<div class=menuskin id=popmenu
onmouseover="clearhidemenu();highlightmenu(event,'on')"
onmouseout="highlightmenu(event,'off');dynamichide(event)"
style="Z-index:100;position:absolute;">
</div>
<TABLE width="757" cellPadding=0 cellSpacing=0 style="WIDTH: 755px" align=
"center">
<TBODY>
<TR> <TD style="VERTICAL-ALIGN: bottom; HEIGHT: 6px" colSpan=3> <TABLE
style="BACKGROUND-IMAGE: url( images/f_head.jpg); WIDTH: 760px;
HEIGHT: 154px"
cellSpacing=0 cellPadding=0> <TBODY>
<TR>
<TD height="110" colspan="6"
style="VERTICAL-ALIGN: text-top; WIDTH: 80px; HEIGHT: 115px;
TEXT-ALIGN: right"></TD>
</TR>
<TR>
<TD height="34" align="center" valign="middle">
<TABLE style="WIDTH: 580px" VERTICAL-ALIGN: text-top;
cellSpacing=0 cellPadding=0 align="center">
<TBODY>
<TR align="center" valign="middle">
<TD style="WIDTH: 100px; COLOR: red;">欢迎您: <?
php echo $_SESSION[username]; ?> </TD>
<TD style="WIDTH: 80px; COLOR: red;"><SPAN style="FONT-
SIZE: 9pt; COLOR: #cc0033"> </SPAN><a href="index.php">
博客首页</a></TD>
<TD style="WIDTH: 80px; COLOR: red;"><a onmouseover=
showmenu(event,productmenu) onmouseout=delayhidemenu()
class='navlink' style="CURSOR:hand" >文章管理</a></TD>
<TD style="WIDTH: 80px; COLOR: red;"><a onmouseover=
showmenu(event,Honourmenu) onmouseout=delayhidemenu()
class='navlink' style="CURSOR:hand">图片管理</a></TD>
<TD style="WIDTH: 90px; COLOR: red;"><a onmouseover=
showmenu(event,myfriend) onmouseout=delayhidemenu()
class='navlink' style="CURSOR:hand" >朋友圈管理</a>
</TD>
<?php
if($_SESSION[fig]==1){
?>
<TD style="WIDTH: 80px; COLOR: red;"><a
onmouseover=showmenu(event,myuser) onmouseout=
delayhidemenu() class='navlink' style="CURSOR:hand"
>管理员管理</a></TD>
<?php
}
?>
<TD style="WIDTH: 80px; COLOR: red;"><a href="safe.
php">退出登录</a></TD>
</TR>
</TBODY>
</TABLE> </TD>
</TR>
</TBODY>
</TABLE></TD>
</TR>
<TR>
<TD colSpan=3 valign="baseline" style="BACKGROUND-IMAGE: url(images/
bg.jpg); VERTICAL-ALIGN: middle; HEIGHT: 450px; TEXT-ALIGN: center">
<table width="100%" height="100%" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="451" align="center" valign="top">
<table width="600" height="100%" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="130" align="center" valign="top"><?php if($page=="")
{$page=1;}; ?>
<table width="560" border="1" align="center" cellpadding="3" cellspacing=
"1" bordercolor="#9CC739" bgcolor="#FFFFFF">
<tr align="left" colspan="2" >
<td width="390" height="25" colspan="3" valign="top"
bgcolor="#EFF7DE"> <span class="tableBorder_LTR"> 查看我的
文章 </span> </td>
</tr>
<?php
if ($page){
$page_size=20; //每页显示20条记录
$query="select count(*) as total from tb_article
where author = '".$_SESSION[username]."' order by
id desc";
$result=mysql_query($query);//查询总的记录条数
$message_count=mysql_result($result,0,
"total"); //为变量赋值
$page_count=ceil($message_count/$page_size);
//根据记录总数除以每页显示的记录数求出所分的页数
$offset=($page-1)*$page_size;
//计算下一页从第几条数据开始循环
$sql=mysql_query("select id,title from
tb_article where author = '".$_SESSION
[username]."' order by id desc limit $offset,
$page_size");
$info=mysql_fetch_array($sql);
?>
<tr>
<td height="31" align="center" valign="top" ><table width=
"500" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><table width="498" border="0" cellspacing="0"
cellpadding="0" valign="top">
<?php
if($info){
$i=1;
do{
?>
<tr>
<td width="498" align="left" valign="top">
<a href="showmy.php?file_id=<?php
echo $info[id];?>"><?php echo $i."、".$info
[title];?></a> </td>
</tr>
<?php
$i=$i+1;
}while($info=mysql_fetch_array($sql))
?>
</table></td>
</tr>
</table></td>
</tr>
<?php } ?>
</table>
<table width="560" border="0" align="center" cellpadding="0"
cellspacing="0">
<tr bgcolor="#EFF7DE">
<td width="33%"> 页次:<?php echo $page;?>/<?php
echo $page_count;?>页
记录:<?php echo $message_count;?> 条 </td>
<td width="67%" align="right" class="hongse01">
<?php
if($page!=1)
{
echo "<a href=myfiles.php?page=1>首页</a>
";
echo "<a href=myfiles.php?page=".($page-1).">
上一页</a> ";
}
if($page<$page_count)
{
echo "<a href=myfiles.php?page=".($page+1).
">下一页</a> ";
echo "<a href=myfiles.php?page=".$page_
count.">尾页</a>";
}
}
?>
</td>
</tr>
</table></td>
</tr>
</table>
</td>
</tr>
</table></TD>
</TR>
</TBODY>
</TABLE>
</body>
</html>
14.5.4 查看博文、评论的实现过程
单击列表中任意一个博文标题,都会看到对应的博文内容和博文评论。查看博文页面(showmy.php)的运行结果如图14-15所示。
系统根据当前页面传过来的博文id值从数据表t_article中返回对应的博文信息(包括博文id、博文作者、博文标题、博文内容和发表时间)、输出文章信息后,开始查找表t_comment中fileid字段值等于文章id的所有评论集,并通过分页显示出来。显示文章页面(showmy.php)的关键代码如下。
<?php
session_start();
include "Conn/conn.php";
include "check_login.php";
$file_id1=$_GET[file_id];
$bool = false;
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<link href="CSS/style.css" rel="stylesheet">
<title>我的文章</title>
<style type="text/css">
<!--
.style1 {color: #FF0000}
-->
</style>
</head>
<script src=" JS/menu.JS"></script>
<script src=" JS/UBBCode.JS"></script>
<script language="javascript">
function check(){
if (document.myform.txt_content.value==""){
alert("评论内容不能为空!");myform.txt_content.focus();return false;
}
}
</script>
<body >
<div class=menuskin id=popmenu
onmouseover="clearhidemenu();highlightmenu(event,'on')"
onmouseout="highlightmenu(event,'off');dynamichide(event)"
style="Z-index:100;position:absolute;">
</div>
<TABLE width="757" cellPadding=0 cellSpacing=0 style="WIDTH: 755px" align=
"center">
<TBODY>
<TR> <TD style="VERTICAL-ALIGN: bottom; HEIGHT: 6px" colSpan=3> <TABLE
style="BACKGROUND-IMAGE: url( images/f_head.jpg); WIDTH: 760px;
HEIGHT: 154px"
cellSpacing=0 cellPadding=0> <TBODY>
<TR>
<TD height="110" colspan="6"
style="VERTICAL-ALIGN: text-top; WIDTH: 80px; HEIGHT: 115px;
TEXT-ALIGN: right"></TD>
</TR>
<TR>
<TD height="34" align="center" valign="middle">
<TABLE style="WIDTH: 580px" VERTICAL-ALIGN: text-top;
cellSpacing=0 cellPadding=0 align="center">
<TBODY>
<TR align="center" valign="middle">
<TD style="WIDTH: 100px; COLOR: red;">欢迎您:
<?php echo $_SESSION[username]; ?> </TD>
<TD style="WIDTH: 80px; COLOR: red;"><SPAN style="FONT-
SIZE: 9pt; COLOR: #cc0033"> </SPAN><a href="index.php">
博客首页</a></TD>
<TD style="WIDTH: 80px; COLOR: red;"><a onmouseover=
showmenu(event,productmenu) onmouseout=delayhidemenu()
class='navlink' style="CURSOR:hand" >文章管理</a></TD>
<TD style="WIDTH: 80px; COLOR: red;"><a onmouseover=
showmenu(event,Honourmenu) onmouseout=delayhidemenu()
class='navlink' style="CURSOR:hand">图片管理</a></TD>
<TD style="WIDTH: 90px; COLOR: red;"><a onmouseover=
showmenu(event,myfriend) onmouseout=delayhidemenu()
class='navlink' style="CURSOR:hand" >朋友圈管理</a>
</TD>
<?php
if($_SESSION[fig]==1){
?>
<TD style="WIDTH: 80px; COLOR: red;"><a
onmouseover=showmenu(event,myuser) onmouseout=
delayhidemenu() class='navlink' style="CURSOR:hand"
>管理员管理</a></TD>
<?php
}
?>
<TD style="WIDTH: 80px; COLOR: red;"><a href="safe.
php">退出登录</a></TD>
</TR>
</TBODY>
</TABLE> </TD>
</TR>
</TBODY>
</TABLE></TD>
</TR>
<TR>
<TD colSpan=3 valign="baseline" style="BACKGROUND-IMAGE: url(images/
bg.jpg); VERTICAL-ALIGN: middle; HEIGHT: 450px; TEXT-ALIGN: center">
<table width="100%" height="100%" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="451" align="center" valign="top">
<table width="600" height="100%" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="130" align="center" valign="middle"><table width=
"560" border="1" align="center" cellpadding="3" cellspacing="1"
bordercolor="#9CC739" bgcolor="#FFFFFF">
<tr align="left" colspan="2" >
<td width="390" height="25" colspan="3" valign="top"
bgcolor="#EFF7DE"> <span class="tableBorder_LTR"> 博
客文章</span> </td>
</tr>
<td align="center" valign="top" ><table width="480" border=
"0" cellpadding="0" cellspacing="0">
<tr>
<td> <?php
$sql=mysql_query("select * from tb_article where id
= ".$file_id1);
$result=mysql_fetch_array($sql);
?>
<table width="100%" border="1" cellpadding="1"
cellspacing="1" bordercolor="#D6E7A5" bgcolor=
"#FFFFFF" class="i_table">
<tr bgcolor="#FFFFFF">
<td width="14%" align="center">博客ID号</td>
<td width="15%"><?php echo $result[id]; ?></td>
<td width="11%" align="center">作
者</td>
<td width="18%"><?php echo $result[author]; ?>
</td>
<td width="12%" align="center">发表时间</td>
<td width="30%"><?php echo $result[now]; ?></td>
</tr>
<tr bgcolor="#FFFFFF">
<td align="center">博客主题</td>
<td colspan="5"> <?php echo $result
[title]; ?></td>
</tr>
<tr bgcolor="#FFFFFF">
<td align="center">文章内容</td>
<td colspan="4"><?php echo $result[content]; ?>
</td>
<td><?php
if($_SESSION[fig]==1 or ($_SESSION
[username] == $result[author])){
$bool = true;
?>
<a href="del_file.php?file_id=<?php echo
$result[id];?>"><img src="images/A_
delete.gif" width="52" height="16" alt="
删除博客文章" onClick="return d_chk();">
</a>
<?php
}
?>
</td>
</tr>
</table></td>
</tr>
</table></td>
</table></td>
</tr>
<tr>
<td height="106" align="center" valign="top"><?php if($page=="")
{$page=1;}; ?>
<table width="560" border="1" align="center" cellpadding="3"
cellspacing="1" bordercolor="#9CC739" bgcolor="#FFFFFF">
<tr align="left" colspan="2" >
<td width="390" height="25" colspan="3" valign="top"
bgcolor="#EFF7DE"> <span class="tableBorder_LTR"> 查
看相关评论</span> </td>
</tr>
<?php
if ($page){
$page_size=4; //每页显示4条记录
$query="select count(*) as total from tb_
filecomment where fileid=' ,m ,' order by id
desc";
$result=mysql_query($query);//查询总的记录条数
$message_count=mysql_result($result,0,
"total"); //为变量赋值
$page_count=ceil($message_count/$page_size); //根据记录总数除以每页显示的记录数求出所分的页数
$offset=($page-1)*$page_size;
//计算下一页从第几条数据开始循环
for ($i=1; $i<2; $i++) {
//计算每页显示几行记录信息
if ($i==1) {
$sql=mysql_query("select * from
tb_filecomment where fileid='$file_id1'
order by id desc limit $offset, $page_size");
$result=mysql_fetch_array($sql);
}
if($result==false){
echo "<font color=#ff0000>对不起,没有相关评
论!</font>";
}
else{
do{
?>
<tr>
<td height="57" align="center" valign="top" ><table width=
"480" border="1" cellpadding="1" cellspacing="1"
bordercolor="#D6E7A5" bgcolor="#FFFFFF" class="i_table">
<tr bgcolor="#FFFFFF">
<td width="14%" align="center">评论ID号</td>
<td width="15%"><?php echo $result[id]; ?></td>
<td width="11%" align="center">评论人</td>
<td width="18%"><?php echo $result[username]; ?></td>
<td width="12%" align="center">评论时间</td>
<td width="30%"><?php echo $result[datetime]; ?></td>
</tr>
<tr bgcolor="#FFFFFF">
<td align="center">评论内容</td>
<td colspan="4"><?php echo $result[content]; ?></td>
<td>
<?php
if ($bool){
?>
<a href="del_comment.php?comment_id=<?php echo
$result[id]?>"><img src="images/A_delete.gif"
width="52" height="16" alt="删除博客文章评论"
onClick="return d_chk();"></a>
<?php
}
?> </td>
</tr>
</table></td>
</tr>
<?php
}while($result=mysql_fetch_array($sql));
}
?>
</table>
<table width="560" border="0" align="center" cellpadding="0"
cellspacing="0">
<tr bgcolor="#EFF7DE">
<td width="52%"> 页次:<?php echo $page;?>/<?php
echo $page_count;?>页
记录:<?php echo $message_count;?> 条 </td>
<td align="right" class="hongse01">
<?php
if($page!=1)
{
echo "<a href=article.php?page=1&file_id=".$file_
id.">首页</a> ";
echo "<a href=article.php?page=".($page-1)."&file_
id=".$file_id.">上一页</a> ";
}
if($page<$page_count)
{
echo "<a href=article.php?page=".($page+1)."&file_
id=".$file_id.">下一页</a> ";
echo "<a href=article.php?page=".$page_count.
"&file_id=".$file_id.">尾页</a>";
}
}
}
?> </td>
</tr>
</table></td>
</tr>
<tr>
<td height="107" align="center" valign="top">
<!-- 发表评论 -->
<form name="myform" method="post" action="check_comment.php">
<table width="560" border="1" align="center"
cellpadding="3" cellspacing="1" bordercolor="#9CC739"
bgcolor="#FFFFFF">
<tr align="left" colspan="2" >
<td width="390" height="25" colspan="3" valign="top"
bgcolor="#EFF7DE"> <span class="right_head"><SPAN
style="FONT-SIZE: 9pt; COLOR: #cc0033"></SPAN></span>
<span class="tableBorder_LTR"> 发表评论</span> </td>
</tr>
<td height="112" align="center" valign="top" >
<input name="htxt_fileid" type="hidden" value="<?php
echo $_GET[file_id];?>">
<table width="500" border="1" cellpadding="1"
cellspacing="0" bordercolor="#D6E7A5" bgcolor=
"#FFFFFF">
<tr>
<td align="center">我要评论</td>
<td width="410"><textarea name="txt_content" cols=
"66" rows="8" id="txt_content" ></textarea></td>
</tr>
<tr align="center">
<td colspan="2"><input type="submit" name="submit"
value="提交" onClick="return check();">
<input type="reset" name="submit2" value="重置">
</td>
</tr>
</table> </td>
</table>
</form>
<!-------------->
</td>
</tr>
</table>
</td>
</tr>
</table></TD>
</TR>
</TBODY>
</TABLE>
</body>
</html>
14.5.5 删除文章、评论的实现过程
在查看博文评论页面,当系统判定当前用户为管理员或是博文作者时,在每篇博文和评论的后面,都将显示相应的“删除”按钮。单击任意的“删除”按钮,系统会提示是否删除,如果确认,将跳转到处理页(del_file.php和del_comment.php),完成删除操作。在删除博文的处理页中,删除博文的同时,也删除了该篇博文的相关的评论。处理页首先在博文列表(t_article)中删除id等于$file_id的记录,如果没有可删除记录,则提示失败,并返回上一步;如果删除成功,则转到评论列表(t_comment)中,删除所有该篇博文的评论。删除博文页(del_file.php)的关键代码如下。
<?php session_start(); include "check_login.php"; include "Conn/conn.php"; $sql="delete from tb_article where id=".$file_id; $result=mysql_query($sql,$link); if($result){ $sql1 = "delete from tb_filecomment where fileid = ".$file_id; $rst1 = mysql_query($sql1,$link); if($rst1) echo "<script>alert('博客文章已被删除!');location='$_SERVER [HTTP_REFERER]';</script>"; else echo "<script>alert('删除失败!');history.go(-1);</script>"; } else{ echo "<script>alert('博客文章删除操作失败!');history.go(-1); </script>"; } ?>