PHP 留言簿(帶Oracle數(shù)據(jù)庫分頁的顯示功能)
發(fā)布時間:2008-10-24 閱讀數(shù): 次 來源:網(wǎng)樂原科技
大部份的網(wǎng)站,都會考慮到和使用者之間的互動關(guān)系。這時,用留言版的功能,可讓使用者留下到此一游,或者是一些和網(wǎng)站的互動訊息。
在設(shè)計上,可以很簡單的只留下使用者的短篇留言,也可以設(shè)計到依性質(zhì)分門別類很復(fù)雜的 Web BBS 系統(tǒng)。當(dāng)然,要如何打造一個屬于自己網(wǎng)站的留言版,就端賴網(wǎng)站的性質(zhì)以及 Web 網(wǎng)站開發(fā)人員的巧思了。
在這里介紹的范例,是簡單的列示所有留言的內(nèi)容。供使用者可以一次看到多筆留言的資料。系統(tǒng)的后端存放留言是用 Oracle 7.x 版的資料庫系統(tǒng)。范例中的資料庫(database) 名稱為 WWW,連線的使用者帳號為 user38、密碼為 iam3849。要直接使用本例,必須先執(zhí)行下面的 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,
msgdate date not null,
email varchar2(1024) null,
msg varchar2(2000) not null,
flag char(1) default 1,
primary key(serial)
);
上面的 SQL 各欄位說明及詳細(xì)資料見下表
序號 欄位 名稱 資料形態(tài) 資料長度 欄位說明 限制 Key
0 流水號 serial varchar2 255 NN PK
1 參照流水號 ref varchar2 255 暫保留。供回
覆留言功能用
2 帳號 id char 8 使用者帳號 NN
3 匿名 alias varchar2 32 顯示的名字 NN
4 網(wǎng)址 ip varchar2 1024 上網(wǎng) IP
5 時間 msgdate date NN
6 電子郵件 email varchar2 1024
7 留言內(nèi)容 msg varchar2 2000 NN
8 顯示旗標(biāo) flag char 1 0: 不顯示
1: 顯示 (內(nèi)定)
在本節(jié)的留言版相關(guān)程式中,若加入了使用者認(rèn)證功能,則可以在 guestbook資料表的帳號欄中留下使用者的認(rèn)證帳號,方便 Webmaster 日后找尋不當(dāng)?shù)陌l(fā)信者。在這兒先留下欄位,讓需要的讀者們實習(xí)了。
要使用本節(jié)的程式,首先要先裝好 Oracle 7.x 版,并確定 Web Server 端的SQL*net 可以順利連上 Oracle 資料庫。之后還要在編譯 PHP 時加
--with-oracle=/home/oracle/product/7.3.2 的選項,當(dāng)然改成其它的路徑也沒關(guān)系,只要該路徑真的是 Oracle 的路徑即可。有關(guān) Oracle 裝設(shè)及使用上的細(xì)節(jié)請參考相關(guān)書籍。
下面的程式是將使用者的留言資訊加到 guestbook 留言資料表中。若要設(shè)定使用者認(rèn)證功能,可在程式剛開始時檢查,發(fā)留言者就可以確認(rèn)身份,而讀取留言就不必身份檢查。這種設(shè)定可以防止不當(dāng)發(fā)言,卻又不會讓留言功能只有少數(shù)人使用。
<?php
file://---------------------------
// 新增留言程式 addmsg.php
// Author: Wilson Peng
// Copyright (C) 2000
file://---------------------------
//
// 可自行在這兒加入身份檢查功能
//
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>內(nèi)容</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
}
?>
上面的程式在執(zhí)行時,先檢查變數(shù) alias 和 msg 是否有資料,若無資料則送出填寫留言的表格到使用者端,供使用者填寫留言。
若使用者填好留言,按下 "送出留言" 的按鈕后,則執(zhí)行程式的前半部份。
程式大概分成五部份
1.. 設(shè)定 Oracle 需要的環(huán)境變數(shù)
2.. 連上 Oracle 資料庫
3.. 整理資料,送入 Oracle 中
4.. 結(jié)束與 Oracle 的連線
5.. 結(jié)束程式,顯示最新的留言資料
在設(shè)定 Oracle 環(huán)境的部份,用 PHP 的函式 putenv(),可設(shè)定作業(yè)系統(tǒng)層的環(huán)境變數(shù)。要使用中文要記得加入下面這行
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 變數(shù)為獨一無二的字串,程式先亂數(shù)產(chǎn)生獨特的字串,再用 md5 編碼,將字串弄亂,形成類似雜湊處理后的無意義字串。由于字串長,又變得很亂,可防止使用者,尤其是駭客或飛客利用序號來戳系統(tǒng)。
$ref 變數(shù)目前是無效的。$id 變數(shù)為使用者認(rèn)證用,若在程式開始處有加入使用者認(rèn)證的程式,則 $PHP_AUTH_USER 會變成使用者的帳號,傳入 $id 變數(shù)中。
至于使用者寫的字串,為了防止資料庫或處理時的復(fù)雜性甘脆將它用 BASE64 編碼??梢宰屩形淖值钠婀肿衷蛔窒В?dāng)然這是鋸箭法,不過對 Web 程式而言,執(zhí)行快速、修改方便才是最重要的,實在沒有必要再浪費精力去處理這些中文的沖碼問題了。值得注意的是使用 BASE64 編碼,會讓字串膨脹大約 1/3,若資料庫的儲存空間有限,可能就不適合用這個方法了,話又說回來,現(xiàn)在硬碟便宜,隨便就是十幾 GB 以
上,應(yīng)該不會考慮資料庫空間有限的問題才對。
最后,將變數(shù)整理成 $query 字串,供資料庫執(zhí)行 SQL 指令使用就可以了。
ora_parse($cursor, $query) or die;
ora_exec($cursor);
ora_close($cursor);
ora_logoff($handle);
要執(zhí)行 Oracle 的 SQL 指令前,要先經(jīng)過 parse 的動作。若在前面加上 @ (如: @ora_prase();),可以不讓使用者看到錯誤訊息。在執(zhí)行 query 指令后,就可以關(guān)閉與 Oracle 之間的連線了。
Header("Location: ./index.php");
exit;
這二行讓瀏覽器重導(dǎo)到 index.php。讓使用者看到他的新留言,就完成了留言的動作。
之后來看看留言的內(nèi)容顯示程式。
<html>
<head>
<meta content="text/html; charset=gb2312"
http-equiv=Content-Type>
<title>留言版</title>
</head>
<body bgcolor=ffffff>
<?php
file://---------------------------
// 留言顯示程式 index.php
// Author: Wilson Peng
// Copyright (C) 2000
file://---------------------------
$WebmasterIPArray =
ay(
"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);
$gu
estbook[$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)."><上頁</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).">下頁></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>
";
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].")
";
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>
在顯示留言的部份,考慮到留言內(nèi)容若很多,加上網(wǎng)路慢的話,可能會讓使用者在線路慢的時候拖累整個資料庫,因此,盡快的連上資料庫,取得需要的資料后,馬上關(guān)閉資料庫,再慢慢送給使用者,應(yīng)是最好的對策。
程式分成四部份
1.. 初始化
2.. 取資料庫中的資料
3.. 計算要顯示的頁數(shù)
4.. 送出資料
這個程式在 BIGLOBE 上有實作,由于這是一間 ISP 公司,因此在設(shè)定時限定撥
接或?qū)>€的會員才能看到,進(jìn)入前要輸入帳號及密碼。有興趣者不妨買個 BIGLOBE 的
撥接帳號參考。為了保護留言者的隱私,留言以馬賽克處理。
$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 程式略
顯示程式和留言程式的初始化部份都差不多,但顯示程式多加了一個功能,設(shè)定Webmaster 的電腦。將 Webmaster 使用的 IP Address 加在 $WebmasterIPArray 陣列變數(shù)中,可以在顯示留言時,顯示刪除留言的字串,方便處理不當(dāng)?shù)牧粞浴?
$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陣列中。取得資料后,就趕緊將資料庫關(guān)閉,再來處理 $guestbook 陣列的資料了。
if ($QUERY_STRING!="") {
$page = $QUERY_STRING;
} else {
$page = 0;
}
這一段程式判斷是要顯示第幾頁,內(nèi)定值是顯示第一頁。要顯示第三頁的頁面,需要使用 http://xxxxxx/index.php?2 的格式,也就是傳入 $QUERY_STRING,余類推。之后的數(shù)行程式,都是用來處理顯示的頁數(shù)及筆數(shù)的資料。
$msgnum=20; // 每頁二十筆
要改變每頁的顯示筆數(shù),可以改 $msgnum 變數(shù)。程式的內(nèi)定值為 20 筆。
for ($i=$start; $i<$end; $i++) {
echo "<p><hr><p>\n";
echo "<p>\n<font color=e06060>".$guestbook[$i][5]."</font> ";
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].") ";
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 陣列的資料按照設(shè)定的頁數(shù)取出,顯示給使用者看。值得一提的是,若看留言的機器 IP 為 $WebmasterIPArray 變數(shù)陣列中的一個元素的話,則會在留言者的匿稱后顯示 "刪除本篇!!" 的字串,供管理人員刪除不當(dāng)留言。
以下即為刪除留言的程式。
<?php
file://---------------------------
// 留言刪除程式 erase.php
// Author: Wilson Peng
// Copyright (C) 2000
file://---------------------------
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 欄位設(shè)成 0 就可以了,不用將資料真的從資料庫上移除。