### PHP 4 完全中文手册

聊天室

聊天室，是 Web 站上打发无聊的人士们的秘密武器。同时，站长或其它人员也可以在这儿杀时间。甚至发生一段轰轰烈烈的网络恋情，就算没有，起码可以增加打字的速度。

聊天室，其实就是多人共同使用的 CGI 程序。程序将每个人输入的字符串，依系统接收完成的时间整理过后，再送给各个用户。而 Web 聊天室和 BBS 的聊天室不同的地方是 BBS 聊天室可以每收到一句话，就马上分送给每位在聊天室的网络用户；Web 由于 CGI 程序不能像 BBS 的 telnet 一直连接，Web CGI 必须以最快的速度将信息送出，然后结束连接。之所以如此，是因为 Web 聊天室使用的是 HTTP 传输协议。在 HTTP 已经实现的版本中，无论是 0.9、1.0 或是 1.1 版都不能长期占据网络连接的 Port。

为了解决资料无法马上传输及更新信息的问题，Netscape 在 3.0 版浏览器之后使用了新的技术，而 Internet Explorer 也实现了这些有 Netscape 研发出来的技术。Netscape 将它分成 Server Push 及 Client Pull 两种技术。Server Push 由 Web 服务器将资料以多重 MIME 编码，送给用户端，目前很少有网站使用这种方式；而 Client Pull 则利用了 HTML 的 meta 标签，并利用 http-equiv="Refresh" 的属性，表示资料要重新载入，至于载入时间，则利用 content 属性进行设定。

<meta> 标签通常都放在 <head>..</head> 部分，以便让浏览器可以尽早准备更新用户端的网页。下面为 meta 和 PHP 合用的例子，配置为每十五秒重新载入一次。

<meta http-equiv="Refresh" content="15; url=<? echo $PHP_SELF; ?>">

如果不用 Server Push 或是 Client Pull 来做聊天室，是否有其它的方法，让 Web 的浏览器能聊天呢？答案是肯定的。可以使用 Java 或是 ActiveX (限 IE4、5) 来做甚至自行开发专属的 Browser Plug-in 程序 (如奇摩的聊天室)，不过这就和 PHP 没有关系了，不是我们的重点。

除此之外，由于定期更新所有网友的留言，为了怕写了一半因为 refresh 而被清掉尚未写好的字符串，因此将聊天室以 frame 页框技术加以实现是有必要的。下例就是聊天室的主程序。

<html> <head> <title>聊天室</title> </head> <frameset rows="*,40" border=1>
<frame src="list.php" name=list scrolling=auto>
<frame src="post.php" name=post scrolling=no>
<noframes>
<body>
本聊天室需使用页框，您的浏览器无法使用
</body>
</noframes>
</frameset>
</html>

程序中以 frame 带出二个 PHP 程序，建议将它们放在同一目录之中，例如 /chatroom，以便日后维护。另外，为了 list.php 及 post.php 可以使用相同的变量，下例将共同的变路路径放在 env.inc 中，可以将它放在 /chatroom 或是 Web 服务器 (如 Apache) 的 PHP include 配置路径中。

<?php // 文件名: env.inc $tempdir="/tmp/"; $chatfile="/tmp/abc"; ?>

聊天室的后端可以设计得很简单，单纯的使用文件来做，也可以弄个数据库，将聊天的内容存入，若是真的很在意系统效率，或许可以考虑使用 UNIX 的行程通讯 IPC 了。

本节即将用户留言的内容放入文件中，在这儿的例子大部份都使用 UNIX/Linux 的外部指令。若系统无该指令 (或称程序)，请自行安装相关程序。

实际上将资料存入文件中比使用数据库还快，若还很在乎速度，可以在 UNIX 机器中装上 RAM Disk，再将文件的存取路径都设在该 RAM Disk 上，保证存取速度能满足严苛的要求。在有些以高速度搜寻引擎为号召的网站，甚至将整个数据库资料都放到 RAM Disk 中，马上让系统速度提高十倍百倍，而且 RAM 的价格和其它解决方案相比的话还算很便宜。若使用 Windows NT，那就没办法了，看微软什么时候提供，或者用 Third Party 的产品了。

有些用户可能对 UNIX 还不是很熟，在这儿先简介会用到的指令：

touch: 建立新文件，或修改旧文件的最后更新日期。

echo 加上两个大于符号: 将字符串显示转向到指定的地方。

tail: 显示文件最后数行的资料，默认值为十行，可使用减号加数字，修改要显示的行数。

下面为送出及处理留言字符串的程序，程序用到 env.inc 的文件。

<?php // 文件名: post.php require("env.inc"); if (($chatuser!="") and ($chattext!="")) { $chatstr="<font color=8080ff>".date("h:i:s")."</font>-<font color=ff8080>".$chatuser."</font>: ".$chattext;
$cmdstr="echo \"".$chatstr."\" >> ".$chatfile;
if (!file_exists($chatfile)) passthru("touch ".$chatfile);
passthru($cmdstr);
}
?><html>
<body bgcolor=ffffff leftmargin=0 topmargin=0 marginheight=0 marginwidth=0>
<form action=<? echo $PHP_SELF; ?> method=post>
<table border=0 width=100%><tr>
<td align=right>匿称:</td>
<td><input type=text name=chatuser size=8 value="<? echo $chatuser; ?>"></td>
<td align=right>发言:</td>
<td><input type=text name=chattext size=30 maxlength=500></td>
<td><div align=right><input type=submit value="送出"></td>
</tr></table>
</form>
</body>
</html>

程序先检查是否有输入字符串，若无匿名及发言内容字符串则显示发言的表单 (Form)，如果资料则将字符串及当时时间存入文件中 (利用 UNIX 的转向指令)。当然，为了防止错误，先检查是否有文件可存文件，若没有则先 touch 该文件，例中的文件就是 /tmp/abc。

<html> <meta http-equiv="Refresh" content="5; url=<? echo $PHP_SELF; ?>"> <meta content="text/html; charset=gb2312" http-equiv=Content-Type> <body bgcolor=ffffff leftmargin=0 topmargin=0 marginheight=0 marginwidth=0> <?
// 文件名: list.php
require("env.inc");
if (!file_exists($chatfile)) {
echo "尚未开张</body></html>";
exit;
}
$uniqfile=$tempdir.uniqid(rand());
$shellcmd="/usr/bin/tail -50 ".$chatfile. " > ".$uniqfile;
passthru($shellcmd);
$chatfilearray=file($uniqfile);
$j=count($chatfilearray);
for ($i=1; $i<=$j; $i++) {
echo $chatfilearray[$j-$i]."<br>\n";
}
unlink($uniqfile);
?>
</body>
</html>

上面的程序就是使用 Client Pull 的技术，每五秒就重新更新一次。同样地，它也 require 共用的 env.inc 文件，要改变其中的变量时，马上就可以让所有的程序用到，这对开发网站来说，是蛮重要的方法，可以将网页程序中都会出现的地方。例如 Copyright (C) 1996-2000 的字符串，放在一个文件上，到了新的一年，只要改一个文件，整个站都改了。

if (!file_exists($chatfile)) {
echo "尚未开张</body></html>";
exit;
}

$uniqfile=$tempdir.uniqid(rand());
$shellcmd="/usr/bin/tail -50 ".$chatfile. " > ".$uniqfile;
passthru($shellcmd);

程序先检查有没有用户发送聊天内容的文件 /tmp/abc，若没有就显示尚未开张，等用户送聊天内容。若已有聊天资料，就取出最后五十条，再在另外的文件中准备显示。

$chatfilearray=file($uniqfile);
$j=count($chatfilearray);
for ($i=1; $i<=$j; $i++) {
echo $chatfilearray[$j-$i]."<br>\n";
}
unlink($uniqfile);

将文件读入数组变量 $chatfilearray 中，并以最后的资料最先显示的方式送给浏览器端，当然可以使用对数组排序的方法，但确定一定时最后存入的资料在最后面，将它排序实在很浪费 CPU 时间，因此就从最后 echo 到最前面的资料。使用完成还要用 unlink() 指令，将临时文件杀掉。

这样就完成了最粗糙的聊天室系统，当然还有很多改进的空间，例如统计使用人数、调用个人....等，就要 Webmaster 再精雕细琢了。

留言板

大部份的网站，都会考虑到和用户之间的互动关系。这时，用留言板的功能，可让用户留下到此一游，或者是一些和网站的互动信息。

在设计上，可以很简单的只留下用户的短篇留言，也可以设计到依性质分门别类很复杂的 Web BBS 系统。当然，要如何打造一个属于自己网站的留言板，须依网站的性质以及 Web 网站开发人员的巧思。

这里介绍的范例，是简单的列示所有留言的内容。供用户可以一次看到多条留言的资料。系统的后端存放留言是用 Oracle 7.x 版的数据库系统。范例中的数据库 (database) 名称为 WWW，连接的用户帐号为 user38、密码为 iam3849。要直接使用本例，必须先执行下面的 SQL 指令，建立 guestbook 的数据表格。

CREATE TABLE guestbook ( serial varchar2(255) not null, ref varchar2(255) null, id char(8) not null, alias varchar2(32)not null,

ip varchar2(1024) null,

msgdatedate not null,

email varchar2(1024) null,

msg varchar2(2000) not null,

flagchar(1) default 1,

primary key(serial)

);

上面的 SQL 各字段说明及详细资料见下表

序号 | 字段 | 名称 | 记录类型 | 记录长度 | 字段说明 | 限制 | Key
0 | 流水号 | serial | varchar2 | 255 |  | NN | PK
1 | 参照流水号 | ref | varchar2 | 255 | 暂保留。供回 覆留言功能用 |  |
2 | 帐号 | id | char | 8 | 用户帐号 | NN |
3 | 匿名 | alias | varchar2 | 32 | 显示的名字 | NN |
4 | 网址 | ip | varchar2 | 1024 | 上网 IP |  |
5 | 时间 | msgdate | date |  |  | NN |
6 | 电子邮件 | email | varchar2 | 1024 |  |  |
7 | 留言内容 | msg | varchar2 | 2000 |  | NN |
8 | 显示标志 | flag | char | 1 | 0: 不显示 1: 显示 (默认) |  |

在本节的留言板相关程序中，若加入了用户认证功能，则可以在 guestbook 数据表的帐号栏中留下用户的认证帐号，方便 Webmaster 日后找寻不当的发信者。在这儿先留下字段，让需要的读者们实习了。

要使用本节的程序，首先要先装好 Oracle 7.x 版，并确定 Web Server 端的 SQL*net 可以顺利连上 Oracle 数据库。之后还要在编译 PHP 时加入 --with-oracle=/home/oracle/product/7.3.2 的选项，当然改成其它的路径也没关系，只要该路径真的是 Oracle 的路径即可。有关 Oracle 装设及使用上的细节请参考相关书籍。

下面的程序是将用户的留言信息加到 guestbook 留言数据表中。若要配置用户认证功能，可在程序刚开始时检查，发留言者就可以确认身份，而读取留言就不必身份检查。这种配置可以防止不当发言，却又不会让留言功能只有少数人使用。

<?php //--------------------------- // 新增留言程序 addmsg.php // Author: Wilson Peng // Copyright (C) 2000
//---------------------------
//
// 可自行在这儿加入身份检查功能
//
if (($alias!="") and ($msg!="")) {
putenv("ORACLE_SID=WWW");
putenv("NLS_LANG=american_taiwan.zht16big5");
putenv("ORACLE_HOME=/home/oracle/product/7.3.2");
putenv("LD_LIBRARY_PATH=/home/oracle/product/7.3.2/lib");
putenv("ORA_NLS=/home/oracle/product/7.3.2/ocommon/nls/admin/data");
putenv("ORA_NLS32=/home/oracle/product/7.3.2/ocommon/nls/admin/data");
$handle=ora_logon("user38@WWW","iam3849") or die;
$cursor=ora_open($handle);
ora_commitoff($handle);
$serial=md5(uniqid(rand()));
$ref="";
$id=$PHP_AUTH_USER;
$ip=$REMOTE_ADDR;
$msg=base64_encode($msg);
$flag="1";
$query="INSERT into guestbook(serial, ref, id, alias, ip, msgdate, email, msg, flag) values('$serial', '$ref', '$id', '$alias', '$ip', sysdate, '$email', '$msg', '$flag')";
ora_parse($cursor, $query) or die;
ora_exec($cursor);
ora_close($cursor);
ora_logoff($handle);
Header("Location: ./index.php");
exit;
} else {
?>
<html>
<head>
<title>填写留言</title>
</head>
<body bgcolor=ffffff>
<form method=POST action="<? echo $PHP_SELF; ?>">
<table border=0 cellpadding=2 width=395>
<tr>
<td nowrap><font color=004080>代号小名</font></td>
<td width=20%><input type=text name=alias size=8></td>
<td nowrap><font color=004080>电子邮件</font></td>
<td width=50%><input type=text name=email size=18></td>
</tr>
<tr>
<td nowrapvalign=top><font color=004080>内容</font></td>
<td width=80% colspan=3><textarea rows=5 name=msg cols=33></textarea></td>
</tr>
<tr>
<td width=100% colspan=4 align=center>
<input type=submit value="送出留言">
<input type=reset value="擦掉留言">
</td>
</tr>
</table>
</form>
</body>
</html>
<?php
}
?>

上面的程序在执行时，先检查变量 alias 和 msg 是否有资料，若无资料则送出填写留言的表格到用户端，供用户填写留言。

若用户填好留言，按下 "送出留言" 的按钮后，则执行程序的前半部份。

程序大概分成五部份

配置 Oracle 需要的环境变量

连上 Oracle 数据库

整理资料，送入 Oracle 中

结束与 Oracle 的连接

结束程序，显示最新的留言资料

在配置 Oracle 环境的部份，用 PHP 的函数 putenv()，可配置操作系统层的环境变量。要使用中文要记得加入下面这行

putenv("NLS_LANG=american_taiwan.zht16big5");

之后就使用 Oracle 函数库的功能: ora_logon() 等等。详见 Oracle 数据库函数库。利用这个函数库，可以很轻易的操作 Oracle 数据库。

再来就是整理资料，以便置入 Oracle 数据库中

$serial=md5(uniqid(rand()));
$ref="";
$id=$PHP_AUTH_USER;
$ip=$REMOTE_ADDR;
$msg=base64_encode($msg);
$flag="1";
$query="INSERT into guestbook(serial, ref, id, alias, ip, msgdate, email, msg, flag) values('$serial', '$ref', '$id', '$alias', '$ip', sysdate, '$email', '$msg', '$flag')";

$serial 变量为独一无二的字符串，程序先随机产生一个独特的字符串，再用 md5 编码，将字符串弄乱，形成类似哈稀处理后的无意义字符串。由于字符串长，又变得很乱，可防止用户，尤其是黑客或飞客利用序号来破解系统。

$ref 变量目前是无效的。$id 变量为用户认证用，若在程序开始处加入了用户认证的程序，则 $PHP_AUTH_USER 会变成用户的帐号，传入 $id 变量中。

至于用户写的字符串，为了防止数据库或处理时的复杂性干脆将它用 BASE64 编码。可以让中文字符的奇怪字符一起消失，当然这是锯箭法，不过对 Web 程序而言，执行快速、修改方便才是最重要的，实在没有必要再浪费精力去处理这些中文的冲码问题了。值得注意的是使用 BASE64 编码，会让字符串膨胀大约 1/3，若数据库的储存空间有限，可能就不适合用这个方法了，话又说回来，现在硬盘便宜，随便就是十几 GB 以上，应该不会考虑数据库空间有限的问题才对。

最后，将变量整理成 $query 字符串，供数据库执行 SQL 指令使用就可以了。

ora_parse($cursor, $query) or die;
ora_exec($cursor);
ora_close($cursor);
ora_logoff($handle);

要执行 Oracle 的 SQL 指令前，要先经过 parse 的步骤。若在前面加上 @ (如: @ora_prase();)，可以不让用户看到错误信息。在执行 query 指令后，就可以关闭与 Oracle 之间的连接了。

Header("Location: ./index.php");
exit;

这二行让浏览器重定向到 index.php。让用户看到他的新留言，就完成了留言的步骤。

之后来看看留言的内容显示程序。

<html> <head> <meta content="text/html; charset=gb2312" http-equiv=Content-Type> <title>留言板</title> </head>
<body bgcolor=ffffff>
<?php
//---------------------------
// 留言显示程序 index.php
// Author: Wilson Peng
// Copyright (C) 2000
//---------------------------
$WebmasterIPArray = array(
"10.0.1.30", // 管理人员甲的机器 IP
"10.0.2.28" // 管理人员乙的机器 IP
);
$WebmasterIP=false;
for ($i=0; $i<Count($WebmasterIPArray); $i++) {
if ($REMOTE_ADDR == $WebmasterIPArray[$i]) $WebmasterIP=true;
}
putenv("ORACLE_SID=WWW");
putenv("NLS_LANG=american_taiwan.zht16big5");
putenv("ORACLE_HOME=/home/oracle/product/7.3.2");
putenv("LD_LIBRARY_PATH=/home/oracle/product/7.3.2/lib");
putenv("ORA_NLS=/home/oracle/product/7.3.2/ocommon/nls/admin/data");
putenv("ORA_NLS32=/home/oracle/product/7.3.2/ocommon/nls/admin/data");
$handle=ora_logon("user38@WWW","iam3849") or die;
$cursor=ora_open($handle);
ora_commitoff($handle);
$query="SELECT serial, ref, id, alias, ip, TO_CHAR(msgdate, 'yyyy/mm/dd hh:mi:ss'), email, msg FROM guestbook where flag='1' order by msgdate desc";
ora_parse($cursor, $query) or die;
ora_exec($cursor);
$i=0;
while(ora_fetch($cursor)) {
$guestbook[$i][0] = ora_getcolumn($cursor,0);
$guestbook[$i][1] = ora_getcolumn($cursor,1);
$guestbook[$i][2] = ora_getcolumn($cursor,2);
$guestbook[$i][3] = ora_getcolumn($cursor,3);
$guestbook[$i][4] = ora_getcolumn($cursor,4);
$guestbook[$i][5] = ora_getcolumn($cursor,5);
$guestbook[$i][6] = ora_getcolumn($cursor,6);
$guestbook[$i][7] = ora_getcolumn($cursor,7);
$i++;
}
ora_close($cursor);
ora_logoff($handle);
echo "<a href=addmsg.php>新增留言....</a><p>\n";
if ($QUERY_STRING!="") {
$page = $QUERY_STRING;
} else {
$page = 0;
}
$i=count($guestbook);
$msgnum=20; // 每页二十条
$start = $page * $msgnum;
$end = $start + $msgnum;
if ($end > $i) $end=$i;
$totalpage=$i/$msgnum;
$pagestr="";
if ($page>0) $pagestr=$pagestr."<a href=index.php?".($page-1).">&lt;上页</a> - ";
$pagestr=$pagestr."[第 ";
for ($i=0; $i<$totalpage; $i++) {
if ($i!=$page) {
$pagestr = $pagestr."<a href=index.php?$i>".($i+1)."</a> ";
} else {
$pagestr = $pagestr.($i+1)." ";
}
}
$pagestr=$pagestr." 页] ";
if ($page<($totalpage-1)) $pagestr=$pagestr."- <a href=index.php?".($page+1).">下页&gt;</a> ";
$pagestr="<div align=center>$pagestr</div>";
echo "<p>".$pagestr."<hr><p>\n";
for ($i=$start; $i<$end; $i++) {
echo "<p><hr><p>\n";
echo "<p>\n<font color=e06060>".$guestbook[$i][5]."</font> &nbsp; ";
if ($guestbook[$i][6]!="") echo "<a href=mailto:".$guestbook[$i][6].">";
echo "<strong>".$guestbook[$i][3]."</strong>";
if ($guestbook[$i][6]!="") echo "</a>";
echo "<br>\n";
if ($WebmasterIP) echo "<a href=erase.php?".$guestbook[$i][0].">删除本篇!!</a> (".$guestbook[$i][2].") &nbsp; ";
echo "<font size=-1 color=c0c0c0>from: ".$guestbook[$i][4]."</font><p>\n";
$msg=base64_decode($guestbook[$i][7]);
$msg=nl2br($msg);
echo $msg;
echo "<p>\n";
}
echo "<p><hr><p>\n";
echo $pagestr;
?>
</body>
</html>

在显示留言的部份，考虑到留言内容若很多，加上网络慢的话，可能会让用户在线路慢的时候拖累整个数据库，因此，尽快的连上数据库，取得需要的资料后，马上关闭数据库，再慢慢送给用户，应是最好的对策。

程序分成四部份

初始化

取数据库中的资料

计算要显示的页数

送出资料

$WebmasterIPArray = array(
"10.0.1.30", // 管理人员甲的机器 IP
"10.0.2.28" // 管理人员乙的机器 IP
);

$WebmasterIP=false;
for ($i=0; $i<Count($WebmasterIPArray); $i++) {
if ($REMOTE_ADDR == $WebmasterIPArray[$i]) $WebmasterIP=true;
}
// 之后初始化 Oracle 程序略

显示程序和留言程序的初始化部份都差不多，但显示程序多加了一个功能，配置 Webmaster 的电脑。将 Webmaster 使用的 IP Address 加在 $WebmasterIPArray 数组变量中，可以在显示留言时，显示删除留言的字符串，方便处理不当的留言。

$handle=ora_logon("user38@WWW","iam3849") or die;
$cursor=ora_open($handle);
ora_commitoff($handle);

$query="SELECT serial, ref, id, alias, ip, TO_CHAR(msgdate, 'yyyy/mm/dd hh:mi:ss'), email, msg FROM guestbook where flag='1' order by msgdate desc";
ora_parse($cursor, $query) or die;
ora_exec($cursor);
$i=0;
while(ora_fetch($cursor)) {
$guestbook[$i][0] = ora_getcolumn($cursor,0);
$guestbook[$i][1] = ora_getcolumn($cursor,1);
$guestbook[$i][2] = ora_getcolumn($cursor,2);
$guestbook[$i][3] = ora_getcolumn($cursor,3);
$guestbook[$i][4] = ora_getcolumn($cursor,4);
$guestbook[$i][5] = ora_getcolumn($cursor,5);
$guestbook[$i][6] = ora_getcolumn($cursor,6);
$guestbook[$i][7] = ora_getcolumn($cursor,7);
$i++;
}
ora_close($cursor);
ora_logoff($handle);

在初始化后，就可以连上 Oracle 数据库，将留言的资料取出放在 $guestbook 数组中。取得资料后，就赶紧将数据库关闭，再来处理 $guestbook 数组的资料了。

if ($QUERY_STRING!="") {
$page = $QUERY_STRING;
} else {
$page = 0;
}

这一段程序判断是要显示第几页，默认值是显示第一页。要显示第三页的页面，需要使用 http://xxxxxx/index.php?2 的格式，也就是传入 $QUERY_STRING，余类推。之后的数行程序，都是用来处理显示的页数及条数的资料。

$msgnum=20; // 每页二十条

要改变每页的显示条数，可以改 $msgnum 变量。程序的默认值为 20 条。

for ($i=$start; $i<$end; $i++) {
echo "<p><hr><p>\n";
echo "<p>\n<font color=e06060>".$guestbook[$i][5]."</font> &nbsp; ";
if ($guestbook[$i][6]!="") echo "<a href=mailto:".$guestbook[$i][6].">";
echo "<strong>".$guestbook[$i][3]."</strong>";
if ($guestbook[$i][6]!="") echo "</a>";
echo "<br>\n";
if ($WebmasterIP) echo "<a href=erase.php?".$guestbook[$i][0].">删除本篇!!</a> (".$guestbook[$i][2].") &nbsp; ";
echo "<font size=-1 color=c0c0c0>from: ".$guestbook[$i][4]."</font><p>\n";
$msg=base64_decode($guestbook[$i][7]);
$msg=nl2br($msg);
echo $msg;
echo "<p>\n";
}

这一段程序就是真正显示留言资料给用户看的程序了。利用 for 循环，将 $guestbook 数组的资料按照配置的页数取出，显示给用户看。值得一提的是，若看留言的机器 IP 为 $WebmasterIPArray 变量数组中的一个元素的话，则会在留言者的匿称后显示 "删除本篇!!" 的字符串，供管理人员删除不当留言。

以下即为删除留言的程序。

<?php //--------------------------- // 留言删除程序 erase.php // Author: Wilson Peng // Copyright (C) 2000
//---------------------------
putenv("ORACLE_SID=WWW");
putenv("NLS_LANG=american_taiwan.zht16big5");
putenv("ORACLE_HOME=/home/oracle/product/7.3.2");
putenv("LD_LIBRARY_PATH=/home/oracle/product/7.3.2/lib");
putenv("ORA_NLS=/home/oracle/product/7.3.2/ocommon/nls/admin/data");
putenv("ORA_NLS32=/home/oracle/product/7.3.2/ocommon/nls/admin/data");
$handle=ora_logon("user38@WWW","iam3849") or die;
$cursor=ora_open($handle);
ora_commitoff($handle);
$query="UPDATE guestbook set flag='0' where serial='".$QUERY_STRING."'";
ora_parse($cursor, $query) or die;
ora_exec($cursor);
ora_close($cursor);
ora_logoff($handle);
Header("Location: ./index.php");
?>

其实这个程序很简单，只要打开 Oracle 数据库，将要删除的序号那条资料的 flag 字段设成 0 就可以了，不用将资料真的从数据库上移除。