首页 » PHP和MySQL Web开发(原书第4版) » PHP和MySQL Web开发(原书第4版)全文在线阅读

《PHP和MySQL Web开发(原书第4版)》31.7 添加新文章

关灯直达底部

了解了以上所有操作后,我们现在可以来看看如何将一篇新文章加入到论坛中去。用户可以使用两种方法来完成该项操作:第一,通过在索引页面点击/"New Post/"按钮,第二,通过在view_post.php页面点击/"Reply/"按钮。

这些动作都将触发相同的脚本,new_post.php,只是带有不同的参数。图31-8显示通过点击/"Reply/"按钮而得到的new_post.php脚本的输出结果。

图 31-8 在回复文章中,父文章的文本将自动插入和标记

首先,让我们查看上图所示的URL:

http://localhost/phpmysql4e/chapter31/new_post.php?parent=5

传递给parent参数值应该是新文章父节点的postid。如果点击了/"New Post/"按钮而不是/"Reply/"按钮,将在URL中得到parent=0的字符串。

其次,可以看到对于一个回复,最初文章的文本被插入进来,而且前面都用“>”字符标记了,这一点与大多数的邮件和新闻阅读程序一样。

第三,可以看到回复消息的默认标题为最初标题加上前缀/"Re:/"。下面,我们来看看产生该输出的代码,如程序清单31-8所示。

程序清单31-8 new_post.php——允许用户对一个已有帖子输入或创建一篇新文章

<?php

include(/'include_fns.php/');

$title=$_POST[/'title/'];

$poster=$_POST[/'poster/'];

$message=$_POST[/'message/'];

if(isset($_GET[/'parent/'])){

$parent=$_GET[/'parent/'];

}else{

$parent=$_POST[/'parent/'];

}

if(!$area){

$area=1;

}

if(!$error){

if(!$parent){

$parent=0;

if(!$title){

$title=/'New Post/';

}

}else{

//get post name

$title=get_post_title($parent);

//append Re:

if(strstr($title,/'Re:/')==false){

$title=/'Re:/'.$title;

}

//make sure title will still fit in db

$title=substr($title,0,20);

//prepend a quoting pattern to the post you are replying to

$message=add_quoting(get_post_message($parent));

}

}

do_html_header($title);

display_new_post_form($parent,$area,$title,$message,$poster);

if($error){

echo/"<p>Your message was not stored.</p>

<p>Make sure you have filled in all fields and

try again.</p>/";

}

do_html_footer;

?>

在完成一些初始化设置之后,该脚本将检查父节点是否为0。如果是0,则表示该文章是一个新主题,而接下来需要完成的操作就相对少些。

如果是一个回复($parent变量是某篇已有文章的postid),以上脚本程序将继续执行并且设置标题和最初消息的文本,如下所示:

//get post name

$title=get_post_title($parent);

//append Re:

if(strstr($title,/'Re:/')==false){

$title=/'Re:/'.$title;

}

//make sure title will still fit in db

$title=substr($title,0,20);

//prepend a quoting pattern to the post you are replying to

$message=add_quoting(get_post_message($parent));

这里用到的函数包括get_post_title、get_post_message和add_quoting。这些函数都来自discussion_fns.php函数库。它们分别如程序清单31-9、程序清单31-10和程序清单31-11所示。

程序清单31-9 discussion_fns.php函数库中的get_post_title函数——从数据库中得到某消息的标题

function get_post_title($postid){

//extract one post/'s name from the database

if(!$postid){

return/'/';

}

$conn=db_connect;

//get all header information from/'header/'

$query=/"select title from header where postid=/'/".$postid./"/'/";

$result=$conn->query($query);

if($result->num_rows!=1){

return/'/';

}

$this_row=$result->fetch_array;

return$this_row[0];

}

程序清单31-10 discussion_fns.php函数库中的get_post_message函数——从数据库中获得某消息的正文

function get_post_message($postid){

//extract one post/'s message from the database

if(!$postid){

return/'/';

}

$conn=db_connect;

$query=/"select message from body where postid=/'/".$postid./"/'/";

$result=$conn->query($query);

if($result->num_rows>0){

$this_row=$result->fetch_array;

return$this_row[0];

}

}

这两个函数分别从数据库中获得特定文章的标题和正文。

程序清单31-11 discussion_fns.php函数库中的add_quoting函数——用“>”符号缩进一则消息的正文

function add_quoting($string,$pattern=/'>/'){

//add a quoting pattern to mark text quoted in your reply

return$pattern.str_replace(/"n/",/"n$pattern/",$string);

}

add_quoting函数将重新格式化字符串,用一个符号开始原始文本的每一行,在默认情况下,该符号为“>”。

用户在回复文章中完成所需输入并且点击/"Post/"按钮后,将进入store_new_post.php脚本程序。图31-9所示的是该脚本的一个示例输出。

图 31-9 新发表的文章在树形结构中显示出来

在上图中,新发表的文章在这行下面Re:using gd?-Laura-Julie-09:36 07/20/2008。不仅如此,该页面看起来还像普通的index.php页面。

下面,我们来看看store_new_post.php的代码,如程序清单31-12所示。

程序清单31-12 store_new_post.php——在数据库中存入新的文章

<?php

include(/'include_fns.php/');

if($id=store_new_post($_POST)){

include(/'index.php/');

}else{

$error=true;

include(/'new_post.php/');

}

?>

可以看到,这是一段很短的脚本程序。它的主要任务是调用store_new_post函数。该页面没有它自身的可见内容。如果保存成功,我们会看到索引页面。否则,将回到new_post.php页,这样,用户可以重试。store_new_post函数如程序清单31-13所示。

程序清单31-13 discussion_fns.php函数库中的store_new_post函数——在数据库中保存并检验新发表的文章

function store_new_post($post){

//validate clean and store a new post

$conn=db_connect;

//check no fields are blank

if(!filled_out($post)){

return false;

}

$post=clean_all($post);

//check parent exists

if($post[/'parent/']!=0){

$query=/"select postid from header where

postid=/'/".$post[/'parent/']./"/'/";

$result=$conn->query($query);

if($result->num_rows!=1){

return false;

}

}

//check not a duplicate

$query=/"select header.postid from header,body where

header.postid=body.postid and

header.parent=/".$post[/'parent/']./"and

header.poster=/'/".$post[/'poster/']./"/'and

header.title=/'/".$post[/'title/']./"/'and

header.area=/".$post[/'area/']./"and

body.message=/'/".$post[/'message/']./"/'/";

$result=$conn->query($query);

if(!$result){

return false;

}

if($result->num_rows>0){

$this_row=$result->fetch_array;

return$this_row[0];

}

$query=/"insert into header values

(/'/".$post[/'parent/']./"/',

/'/".$post[/'poster/']./"/',

/'/".$post[/'title/']./"/',

0,

/'/".$post[/'area/']./"/',

now,

NULL

)/";

$result=$conn->query($query);

if(!$result){

return false;

}

//note that our parent now has a child

$query=/"update header set children=1 where postid=/'/".$post[/'parent/']./"/'/";

$result=$conn->query($query);

if(!$result){

return false;

}

//find our post id,note that there could be multiple headers

//that are the same except for id and probably posted time

$query=/"select header.postid from header left join body

on header.postid=body.postid

where parent=/'/".$post[/'parent/']./"/'

and poster=/'/".$post[/'poster/']./"/'

and title=/'/".$post[/'title/']./"/'

and body.postid is NULL/";

$result=$conn->query($query);

if(!$result){

return false;

}

if($result->num_rows>0){

$this_row=$result->fetch_array;

$id=$this_row[0];

}

if($id){

$query=/"insert into body values

($id,/'/".$post[/'message/']./"/')/";

$result=$conn->query($query);

if(!$result){

return false;

}

return$id;

}

}

这是个很长的函数,但它并不太复杂。它之所以长,是因为插入一篇文章就意味着要标题表和正文表进行插入操作,并要在标题表中更新父文章行以表明它现在有子文章了。

以上就是该Web论坛应用程序的所有代码。