首页里用到了很多“{}”包括的字符,里面的内容是变量,因为论坛信息会随一些操作而改变而不同的显示状态,这些信息将随这些状态的改变而改变成及时的真实的状态。这些是要与数据库连接的,所以下面将说明数据库的连接函数。
3.2 数据库连接函数
数据库连接在论坛运行中是必不可少的,把这部分单独做成一个函数,在需要的时候只需要调用这个函数就可以了,而不用每次去写连接程序,这种复用可以让操作更加方便快捷。
选择的Access作为数据库,功能不强大,不能让很多人连接,但是可以省掉很多设置,对机器要求也相对要低得多,适合用PC机架设论坛。ASP中与数据相关紧密的是ADO,要让ADO对象能存取数据库,最重要的东西是OLE DB和ODBC的驱动程序,必须具备对应数据库的其中一种驱动程序,ADO对象才能进行存取。因为根据Microsoft公司的说法,OLE DB驱动程序的执行效能比ODBC要好,所以选择用OLE DB驱动程序。
利用ADO的Connection来建立同数据库的连接。建立ADODB.Connection对象,使用此对象的Open方法打开数据库。用Access在论坛路径下建立一个数据库存储路径“data”,然后建立一个名为mybbs7.mdb的数据库,建立之前数据库设计中的表。利用Microsoft公司的OLE DB机制连接Access,用OLE DB不用建立ODBC就可以直接连接Access数据库。见程序3-2。
程序3-2 Access数据库连接
Sub ConnectionDatabase
Dim ConnStr
Db=”data/mybbs7.mdb”
ConnStr=”Provider=Microsoft.jet.OLEDV.4.0”Data Source=”& Server.MapPath(db)
Set conn=Server.CreateObject(“ADODB.Connection”)
Conn.open ConnStr
if Err Then
Err.Clear
Set Conn=Nothing
Response.Write ”数据库连接出错,请检查连接字符串。”
Response.End
End if
End Sub
Sub声明了函数ConnectionDatabase,End Sub结束这个函数。Dim声明了变量ConnStr,这个变量是用来存储连接数据库信息的。变量Db声明了数据库文件所在的路径。为ConnStr赋值是声明OLE DB连接数据库的方式,Data Source后面跟的是数据库文件所在的路径。Server.MapPath是ASP内置Server对象一个函数,用来取得网站目录下文件的绝对路径。7~12行是一个判断错误的信息,如果连接出错,Asp的Err对象判断系统给出错误的存在,然后清除。
第四章 模块的实现
4.1 用户模块
4.1.1 用户的登陆
首先看用户的登陆。在用户信息表里用户名和用户密码字段是用来验证用户身份的,用这两个字段来写验证用户登陆的程序。
登陆页面命名为Login.asp,这个页面包含了输入用户名和密码、Cookie选项、和隐身登陆选项。隐身登陆只是一个判断登陆状态的标识。主要是验证用户身份和把用户信息写入Cookie。
首先看验证用户身份的程序,如程序4-1。
程序4-1 验证用户身份程序(Login.asp)
sqlstr=" UserName='"&username&"'"
Sql="Select UserID,UserName,UserPassword,UserEmail,UserPost,UserTopic,UserSex,UserFace,
UserWidth,UserHeight,JoinDate,LastLogin,UserLogins,Lockuser,Userclass,UserGroupID,
UserGroup,userWealth,userEP,userCP,UserPower,UserBirthday,UserLastIP,UserDel,UserIsBest,
UserHidden,UserMsg,IsChallenge,UserMobile,TitlePic,UserTitle,TruePassWord,UserToday "
Sql=Sql+" From [Dv_User] Where "&sqlstr&""
set rsUser=Mybbs.Execute(sql)
If rsUser.eof and rsUser.bof Then
ChkUserLogin=false
Exit Function
Else
iMyUserInfo=rsUser.GetString(,1, "|||", "", "")
rsUser.Close:Set rsUser = Nothing
End If
iMyUserInfo = "Mybbs|||"& Now & "|||" & Now &"|||"& Mybbs.BoardID &"|||"& iMyUserInfo
&"||||||Mybbs"
iMyUserInfo = Split(iMyUserInfo,"|||")
If trim(password)<>trim(iMyUserInfo(6)) Then
ChkUserLogin=false
ElseIf iMyUserInfo(17)=1 Then
ChkUserLogin=false
ElseIf iMyUserInfo(19)=5 Then
ChkUserLogin=false
Else
ChkUserLogin=True
Session(Mybbs.CacheName & "UserID") = iMyUserInfo
Mybbs.UserID = iMyUserInfo(4)
RegName = iMyUserInfo(5)
Article = iMyUserInfo(8)
UserLastLogin = iMyUserInfo(15)
UserClass = iMyUserInfo(18)
GroupID = iMyUserInfo(19)
TitlePic = iMyUserInfo(34)
If Article<0 Then Article=0
End If
首先是一个查询用户身份的SQL语句,输入某个用户后将从数据表User_T中查找该用户。set rsUser=Mybbs.Execute(sql)一句是用来执行这条SQL语句,同时返回一个包含了查询信息的记录集。If rsUser.eof and rsUser.bof Then一句判断用户信息是否存在。如果不为空,就将把数据集的信息写入储存用户信息的字符串中。If trim(password)<>
trim(iMyUserInfo(6)) Then一句判断用户密码是否和数据库中的用户密码相同。
Cookie是对于一些有限制注册用户才能看的页面用来识别是否登陆的。是由Web页服务器置于你硬盘上的一个很小的文本文件,一般不超过4KB。程序4-2是把用户信息写入Cookie的程序。
程序4-2 把用户信息写入Cookie(Login.asp)
select case usercookies
case "0"
Response.Cookies(Mybbs.Forum_sn)("usercookies") = usercookies
case 1
Response.Cookies(Mybbs.Forum_sn).Expires=Date+1
Response.Cookies(Mybbs.Forum_sn)("usercookies") = usercookies
case 2
Response.Cookies(Mybbs.Forum_sn).Expires=Date+31
Response.Cookies(Mybbs.Forum_sn)("usercookies") = usercookies
case 3
Response.Cookies(Mybbs.Forum_sn).Expires=Date+365
Response.Cookies(Mybbs.Forum_sn)("usercookies") = usercookies
end select
Response.Cookies(Mybbs.Forum_sn).path = Mybbs.cookiepath
Response.Cookies(Mybbs.Forum_sn)("username") = regname
Response.Cookies(Mybbs.Forum_sn)("userid") = Mybbs.UserID
Response.Cookies(Mybbs.Forum_sn)("password") = TruePassWord
Response.Cookies(Mybbs.Forum_sn)("userclass") = userclass
Response.Cookies(Mybbs.Forum_sn)("userhidden") = userhidden
Response是ASP的一个内置对象,Cookies是这个对象用来向浏览器写Cookie文件的集合。Cookies集合设置Cookie的值。若指定的Cookie不存在,则创建它,若存在。则设置新的值并且将旧值删除。Response.Cookies(Mybbs.Forum_sn).Expires=Date+1是用来保存用户选择的Cookie保存时间的,在选择时间内再次来论坛则可以不用再登陆了。
4.1.2 用户的注册
用户注册也关系到信息的验证,必须确定一些信息符合一定的规则和要求。用户注册后可以修改自己的信息和密码,如果忘记密码还有相关取回密码的操作。
首先就是用户的注册,命名为reg.asp,主要是对用户所填写信息的检测。主要包括字段是否为空,是不是满足长度、字符方面的要求;输入E-mail是否正确,主要判别是@字符是否存在和存在的位置;两次输入的密码是否一致;用户名是否已经存在,电子邮件是否被使用。
注册首先是要向数据库提交你所填写的信息,这些所填写的信息大多是表单的形式,可以使用Request.form()来获取表单内的文本框。Request是ASP的内置对象,Form是Request的一个获得表单的集合。
(1) 用户名的验证:在获取的同时就可以对文件长度等进行检测,使用Cint()函数进行强制执行整数运算判断是否在可接受的范围之内。
Cint(Mybbs.Forum_Setting(41)) or strLength(Request.form("name"))
0 or Instr(username,"%")>0 or Instr(username,chr(32))>0 or
Instr(username,"?")>0 or Instr(username,"&")>0 or Instr(username,";")>0 or Instr(username,",")>0
or Instr(username,"'")>0 or Instr(username,",")>0 or Instr(username,chr(34))>0 or
Instr(username,chr(9))>0 or Instr(username,"")>0 or Instr(username,"$")>0
(2) 密码的验证:主要验证的是密码的长度,采用Len()函数,可以返回字符串中字符的个数。参数可以是字符串也可以是变量名。
If Request.form("psw")="" or len(Request.form("psw"))>10 or len(Request.form("psw"))<6 Then
ErrCodes=ErrCodes+"
"+template.Strings(13)
(3) 电子邮件的验证:邮件的地址一般是“用户名@域名”,采用VBScript的函数Split(),可以返回一个一维数组。在参数部分可以设置“@”为字符串的标识界限。用这个符号来拆分电子邮件地址,形成数组。UBound()函数返回了数组维数的最大可用下标。
Dim names,name,i,c
Is ValidEmail=true
Names=Split(email,”@”)
If UBound(names)<>1 then
Is VailEmail=false
Exit function
End If
而用户的注册信息如果是合法的则在提交注册信息后要将这个注册信息插入到数据库中去,可以使用Recordset对象。
set rs=Server.CreateObject(“ADODB.Recordset”)
sql=”select * from [User_T]
rs.open sql,conn,2,3
rs.addnew
rs(“Username”)=username
rs(“Userpassword”)=password
rs(“UserEmail”)=useremail
rs(“Userclass”)=userclass
rs(“TitlePic”)=titlepic
rs.update
rs.close
set rs=nothing
但光有Recordset对象没有Connection对象也没有用,Connection对象已经写入了连接数据库的函数Conn.asp。
ConnStr = "Provider = Microsoft.Jet.OLEDB.4.0;Data Source = " & Server.MapPath(db)
Set conn = Server.CreateObject("ADODB.Connection")
conn.open ConnStr
set rs=server.createobject("adodb.recordset")
sql="select * from [User_T] where username=’”&username&”’
rs.open sql,conn,1,3
在上面程序里,conn对象的功能是连接数据库,rs的功能是打开数据表User_T。而Connection对象的功能是连接数据库,连接程序如下:
Sub ConnectionDatabase
Dim ConnStr
Db = "data/mybbs7.mdb"
ConnStr = "Provider = Microsoft.Jet.OLEDB.4.0;Data Source = " & Server.MapPath(db)
Set conn = Server.CreateObject("ADODB.Connection")
conn.open ConnStr
ConnStr = "Provider = Microsoft.Jet.OLEDB.4.0;Data Source = " & Server.MapPath(db)一句分别设置了Provide参数和Data Source参数。
用户注册后要修改自己的信息。修改信息就是将原来用户的信息显示出来,待用户修改提交表单后更新数据库中的信息,这里同样要对用户新输入的信息进行检测,这个和用户注册部分的检测是一样的,只是没有了对用户名的检测。所以用户信息的修改的程序与用户注册是很相似的,只少了rs.addnew一句,另外在选取信息的时候的语句有所不同。
sql=”Select * from [User_T]” where userid=”& UserID
通过这一句可以准确的定位到用户的编号UserID的这条记录,这是利用了Recordset对象的查询功能,然后使用Recordset对象的写入功能,用rs.Update结束。
虽然用户的用户名不可以更改,但是用户的密码是可以更改的,这是用户身份验证的标识,同时也可以更改自己的密码提问和密码答案。这些更改也基本上和用户信息修改的程序相同,利用用户的编号取出用户的信息,验证用户的修改信息后更新数据库。
但是如果用户是忘记了密码而要取回,则就要调用到另外的一套程序。见程序4-3。
程序4-3 获得用户密码程序(Lostpass.asp)
If request.Form("username")="" Then
showerr template.Strings(6)
Exit Sub
Else
username=replace(request("username"),"'","")
End If
If Mybbs.Forum_Setting(2)<>"0" Then
Set Rs=Mybbs.execute("Select UserQuesion,userAnswer,Username,Usergroupid from [Dv_user] where username='"&username&"'")
Else
Set Rs=Mybbs.execute("Select UserQuesion,userAnswer,Username,Usergroupid from [Dv_user] where username='"&username&"' and UserGroupID>3")
End If
If rs.eof and rs.bof then
showerr template.Strings(8)
Exit Sub
ElseIf rs(3) < 4 then
showerr template.Strings(7)
Exit Sub
Else
If rs(0)="" or isnull(rs(0)) Then
showerr template.Strings(9)
Exit Sub
Else
template.html(6)=Replace(template.html(6),"{$Quesion}",Rs(0))
template.html(6)=Replace(template.html(6),"{$username}",username)
If Mybbs.forum_setting(81)="0" Then
template.html(6)=Replace(template.html(6),"{$getcode}","")
Else
template.html(6)=Replace(template.html(6),"{$getcode}"," 验证码:
"&Mybbs.GetCode())
End If
Response.Write template.html(6)
End If
End If
Rs.Close
Set Rs=Nothing
这里是通过两步来完成取回密码的,第一步是验证用户名,第二步才是取回密码。
4.1.3 浏览其他用户信息
如程序4-4。
程序4-4 用户列表程序(dispuser.asp)
UPSQL="update [Dv_user] set UserViews=UserViews+1 "
SQL=" Select UserID,UserName,UserPassword,UserEmail,UserPost,UserTopic,UserSign,UserSex,
UserFace,UserWidth,UserHeight,UserIM,JoinDate,LastLogin,UserLogins,UserViews,Lockuser,
Userclass,UserGroup,userWealth,userEP,userCP,UserTitle,UserBirthday,UserQuesion,UserAnswer,
UserLastIP,UserPhoto,UserFav,UserPower,UserDel,UserIsBest,UserInfo,UserSetting,UserGroupID,
TitlePic,UserHidden,UserMsg,IsChallenge,UserMobile From [Dv_User] "
If ShowUserid="" Then
UPSQL=UPSQL + " Where Username='"&UserName&"'"
SQL=SQL + " Where Username='"&UserName&"'"
Else
UPSQL=UPSQL + " Where Userid="&ShowUserid
SQL=SQL + " Where Userid="&ShowUserid
End If
Set Rs=Mybbs.Execute(Sql)
If Rs.Eof And Rs.Bof Then
Mybbs.AddErrCode(32)
Exit Sub
Else
Mybbs.Execute(UPSQL)
'UserInfo=Rs.GetRows(1)
SQL=Rs.GetString(,1, "@@@", "", "")
Rs.Close:Set Rs=Nothing
End if
UserInfo=Split(Sql,"@@@")
ShowUserid=Clng(UserInfo(0))
UserName=UserInfo(1)
前面的SQL语句和用户修改信息很相似,实际上就是修改用户信息的另外一种方法。Rs.GetString(,1, "@@@", "", "")这个方法是将Recordset作为字符串返回,Getstring可以有4个参数,这里只用到两个。因为浏览用户只需要从数据库中读取一条记录,所以这里的第二个参数为1,@@@是用来分割记录集字符串。使用这个方法会使读取记录的速度比较快,从而提高ASP的效率。
4.2 版面与公共信息模块
4.2.1 版面浏览
版面浏览是指版面的列表,版面有层次之分,一般以两层的方式显示。在一级版面下,依次显示子版面。可以使用几个函数来完成,如程序4-5。
程序4-5 版面浏览函数
‘函数一(获得某版面下的子版面):
Public Function ReloadBoardInfo(lBoardID)
If lBoardID=0 Then Exit Function
Dim Rs
Set Rs=Execute("select BoardID,BoardType,ParentID,ParentStr,Depth,RootID,Child,readme,
BoardMaster,PostNum,TopicNum,indexIMG,todayNum,boarduser,LastPost,Sid,Board_Setting,
Board_Ads,Board_user,IsGroupSetting,BoardTopStr,BoardID As TempStr,BoardID As TempStr1,
BoardID As TempStr2,BoardID As TempStr3,cid,BoardID As TempStr4 from Dv_board where
BoardID="&lBoardID)
If Not Rs.Eof Then
Name = "BoardInfo_" & lBoardID
Value = Rs.GetRows(1)
Else
'自动修正所有版面的boards数
Call ReloadAllBoardInfo()
'Response.Redirect "index.asp"
End If
Rs.Close
Set Rs = Nothing
End Function
‘函数二(自动修正所有版面的boards数)
Public Sub ReloadAllBoardInfo()
Dim Rs,Boards
Set Rs=Execute("Select BoardID From Dv_Board Order By RootID,Orders")
If Not Rs.Eof Then
Boards=Rs.GetString(,-1, "",",","")
Boards=Left(Boards,Len(Boards)-1)
End If
Rs.close:Set Rs=Nothing
Execute("Update dv_Setup Set Forum_Boards='"&Boards&"'")
ReloadSetupCache Boards,27
End Sub
Value = Rs.GetRows(1)一句用到了GetRows()方法,其作用是将Recordset对象的多个记录检索到数组中。GetRows可以带3个参数,这里只用到了第一个参数。在调用了GetRows后,下一个未读取的记录就成了当前记录。如果没有其他记录,则EOF的属性将被设置成True。
4.2.2 公共信息模块
公共信息有两类,一类是可以在版面的顶端可以看到的论坛信息,一类是由用户发起的在各个版面的信息,他的功能类似于广播,称之为小字报。一般公告具有时效性,要求只有管理员才能发布,而版主可以在其负责的版区发布。小字报则可有各个会员发布,且版主可以管理这些小字报。发布公告和帖子的原理是一样的,而只需要识别用户的身份来判断是否有发布和管理权限。如程序4-6。
程序4-6 判断用户身份程序(announcements.asp)
程序一:
Select case UserGroupID
Case 4 Vipuser=True
Case 3 Boardmaster=True
Case 2 Superboardmaster=True
Case 1 Master=True
End Select
程序二:
If Mybbs.Master Then
Mybbs. Boardmaster=True
ElseIf Mybbs. Superboardmaste Then
Mybbs. Boardmaster=True
ElseIF Mybbs.UserGroupID=3 And Not Trim(Mybbs. BoardmasteList)=”” Then
IF InStr(“|”&lcase(Mybbs. BoardmasteList)&”|”,”|”&lcase(Mybbs.Membername)&”|”)>0 Then
Mybbs. Boardmaste=True
End If
End If
注意UserGroupID和Mybbs.Membername两个变量,因为当用户登陆都其登陆信息会写如Cookie,这里面的变量信息就是从Cookie里面获得的。
4.3 帖子模块
一个论坛最重要的是数据,数据部分最重要的只有两个,一个是用户数据,另一个就是帖子数据。而帖子是一个论坛存在的根本,所以非常重要。
4.3.1 发布、修改、删除帖子
对于发布、修改和删除帖子,发布是重点,修改帖子和发布帖子是差不多的,而删除帖子只需要多数据库的帖子ID实行删除操作,相对也比较简单。发布帖子的功能很多,使用心情图片和表情图片,正文部分可以自己定义喜欢的格式,还有使用各种UBB代码。
帖子的正文部分可以通过一些代码插图图片、Flash等各种东西,而且可以自定义字体、格式、颜色等,让帖子看起来更丰富多彩。其实这里并没有提供HTML功能,而是用到了UBB码。UBB代码是HTML的一个变种,是Ultimate Bulletin Board(国外的一个BBS程序)采用的一种特殊的TAG。为了避免用户无意或有意的使用HTML代码对论坛进行攻击,一般论坛是禁止HTML代码的,但会开放一些自定义的Tag标签,类似与HTML中的Tag,这样就既可以使用一些等同于HTML代码的功能,又避免了论坛受到恶意的攻击。一般我们自定义的这些Tag叫做UBB代码。
(1) URL超级连接:直接输入http://bbs.emu618.com系统将直接创建超级链接。
[url]http://bbs.emu618.com[/url]
或者可以使用
[url=http://bbs.emu618.com]EMU618论坛[/url]
(2) E-mail超级连接:在你的信息里加入电子邮件的超级链接,可以按下面的方式套用UBB代码。
[email]feilusaidi@hotmail.com[/email]
(3) 粗体与斜体:可以使用[b][/b]来表示粗体,[i][/i]来表示斜体
(4) 列表:在信息里加入列表,按照下例套用UBB代码
[list]
[*] firstline
[*] secondline
[/list]
如果要加入序列可以使用[list=A]或[list=1]就可以按照字母和数字来排序了。
(5) 加入图片:[img]图片地址[/img]可以在文章中插入图片。
(6) 引用信息:[quote]引用内容[/quote]可以插入引用的信息。
(7) 保持格式:如果需要帖入一些按一定格式排列的字符图可以使用[code]内容[/code],这样里面的内容会按照你帖入的格式严格排列。
(8) 彩色文字:[color=red]文字[/color]可以让文字变成彩色。这里red是论坛已经定义好的彩色列表,red=#FF0000,用户也可以自己定义其他非论坛定义的色彩。
以上是关于基本UBB代码的使用,而在实际操作时对于UBB代码也可以进行过滤,引用别人的发言时也可以使用直接引用选项,自动完成UBB操作。见程序4-7和4-8。
程序4-7 UBB过滤程序(post.asp)
Function cutStr(str,strlen)
Dim re
Set re=new RegExp
re.IgnoreCase =True
re.Global=True
re.Pattern="<(.[^>]*)>"
str=re.Replace(str,"")
set re=Nothing
Dim l,t,c,i
l=Len(str)
t=0
For i=1 to l
c=Abs(Asc(Mid(str,i,1)))
If c>255 Then
t=t+2
Else
t=t+1
End If
If t>=strlen Then
cutStr=left(str,i)&"..."
Exit For
Else
cutStr=str
End If
Next
cutStr=Replace(cutStr,chr(10),"")
cutStr=Replace(cutStr,chr(13),"")
End Function
程序4-7的用处是过滤掉所有HTML代码的标记。
程序4-8 引用他人发言程序(post.asp)
Function Ubb2Html(str)
If Str<>"" And Not IsNull(Str) Then
Dim re
Set re=new RegExp
re.IgnoreCase =True
re.Global=True
re.Pattern="(>)("&vbNewLine&")(<)"
Str=re.Replace(Str,"$1$3")
re.Pattern="(>)("&vbNewLine&vbNewLine&")(<)"
Str=re.Replace(Str,"$1$3")
re.Pattern=vbNewLine
Str=re.Replace(Str," ")
re.Pattern="( )"
Str=re.Replace(Str," ")
re.Pattern="<\/I>"
Str=re.Replace(Str,"")
re.Pattern="(
)"
Str=re.Replace(Str," ")
re.Pattern="<(\w+)( )+([^>]*)>"
Str = re.Replace(Str,"<$1 $3>")
If Request("reply")="true" Then
re.Pattern="(
以下是引用(.|\n)*<\/div>)"
Str=re.Replace(Str,"")
re.Pattern="(\[quote\]以下是引用(.|\n)*\[\/quote\])"
Str=re.Replace(Str,"")
re.Pattern="(\[quote\]\[b\]以下是引用(.|\n)*\[\/quote\])"
Str=re.Replace(Str,"")
End If
Set Re=Nothing
Ubb2Html = Str
Else
Ubb2Html = ""
End If
End Function
这两个程序都有<% Set re=RegExp %>这样的一句,RegExp储存有关正则表达式模式匹配结果的信息。此对象不能显示构造,用法是RegExp(“模式”[,”标记”])。模式表示正则表达式的文本,标记可以全定匹配(g)或忽略大小写的匹配(i)。
帖子的修改和发布是基本上相同的,不同的是修改时要取得原来帖子的全部内容,这些内容都储存在帖子信息表bbs1_T的Body字段。而删除帖子只需要对帖子信息表的相关帖子的ID进行删除操作,但要注意的是如果删除的是主题,则需要把与主题ID相关的帖子ID都进行删除,这里要进行一个筛选。
4.3.2 帖子浏览模块
帖子浏览模块部分最重要的是对数据库的操作,如帖子的分页列表、搜索等。帖子的分页程序见程序4-9。
程序4-9 帖子分页程序(list.asp)
Function Show_List_Topic()
Dim Cmd,limitime,SQL,Rs,i,TempStr,ti,TopicTempStr
Dim Posttime
If IsSqlDataBase=1 And IsBuss=1 Then
Set Cmd = Server.CreateObject("ADODB.Command")
Set Cmd.ActiveConnection=conn
Cmd.CommandText="dv_list"
Cmd.CommandType=4
Cmd.Parameters.Append cmd.CreateParameter("@boardid",3)
Cmd.Parameters.Append cmd.CreateParameter("@pagenow",3)
Cmd.Parameters.Append cmd.CreateParameter("@pagesize",3)
Cmd.Parameters.Append cmd.CreateParameter("@tl",3)
Cmd.Parameters.Append cmd.CreateParameter("@topicmode",3)
Cmd.Parameters.Append cmd.CreateParameter("@totalrec",3,2)
Cmd("@boardid")=Mybbs.BoardID
Cmd("@pagenow")=page
Cmd("@pagesize")=Cint(Mybbs.Board_Setting(26))
Cmd("@topicmode")=TopicMode
If limitime="" Then
Cmd("@tl")=0
Else
Cmd("@tl")=limitime
End If
set Rs=Cmd.Execute
Else
Set Rs = server.CreateObject ("adodb.recordset")
If Cint(TopicMode)=0 Then
Sql="Select TopicID,boardid,title,postusername,postuserid,dateandtime,child,hits,votetotal,
lastpost,lastposttime,istop,isvote,isbest,locktopic,Expression,TopicMode,Mode From Dv_Topic
Where BoardID="&Mybbs.BoardID&" And IsTop=0 Order By LastPostTime Desc"
End If
Rs.Open Sql,Conn,1,1
End If
Mybbs.SqlQueryNum = Mybbs.SqlQueryNum + 1
If Not (Rs.Eof And Rs.Bof) Then
If IsSqlDatabase = 1 And IsBuss=1 Then
SQL=Rs.GetRows(-1)
Else
If TopicNum Mod Cint(Mybbs.Board_Setting(27))=0 Then
n = TopicNum \ Cint(Mybbs.Board_Setting(27))
Else
n = TopicNum \ Cint(Mybbs.Board_Setting(27))+1
End If
Rs.MoveFirst
If page > n Then page = n
If page < 1 Then page = 1
If page >1 Then
Rs.Move (page-1) * Clng(Mybbs.Board_Setting(26))
End if
If Rs.Eof Then Exit Function
SQL=Rs.GetRows(Mybbs.Board_Setting(26))
End If
'TopicID,boardid,title,postusername,postuserid,dateandtime,child,hits,votetotal,lastpost,lastpostti
me,istop,isvote,isbest,locktopic,Expression,TopicMode,Mode
Dim Showtitle,postusername
With Response
For ti=0 To Ubound(SQL,2)
‘显示帖子部分省略
Next
SplitPageNum=Ubound(SQL,2)+1
SQL=Null
If TopicNum Mod Cint(SplitPageNum)=0 Then
n = TopicNum \ Cint(SplitPageNum)
Else
n = TopicNum \ Cint(SplitPageNum)+1
End If
If action="batch" And Mybbs.GroupSetting(45)=1 Then
Dim Forum_Boards,Board_Datas,BoardJumpList,ii,Depth
Forum_Boards=Split(Mybbs.CacheData(27,0),",")
‘显示部分省略
End If
If Forum_AllTopNum = 0 And ti = 0 Then Response.Write template.html(4)
SQL=Null
Rs.Close
Set Rs=Nothing
Set Cmd=Nothing
End Function
看<% Set Cmd = Server.CreateObject("ADODB.Command") %>一句,这里用到了ADODB的Command对象,定义要对数据源执行的特殊命令,使用Command对象查询数据库并返回Recordset对象中的记录,以便执行大量的操作或对数据库结构进行操作。
为了提高页面的读取速度,帖子一般不会在一页里罗列出来,而是采用分页显示,让每页显示一定的帖子数。论坛的分页显示主要有两种方法,一种是将数据库中所有符合查询条件的记录一次性读入Recordset中,并存放在内存中,然后通过ADO Recordset对象所提供的几个专门支持分页处理的属性来管理分页处理;另一种方法是根据客户的指示,每次分别从符合查询条件的记录中将规定数目的记录读出显示。两种方法的区别在于前者要把所有记录都读入内存,如果记录很多的话,效率会比较低;而后者是先根据指示做判断再读入符合条件的一定数目的记录进内存,但如果访问人数多时,会造成很大负担。因为在一般情况下效率相差不大,而第一种方法更容易实现,所以一般采取第一种方法。在第一种方法中,进行ADO存取数据库时的分页显示,其实就是对Recordset的记录进行操作。Recordset对象表示基本表或命令执行结果的记录全集。任何时候Recordset都只将集合中的单个记录作为当前的记录引用。使用ADO时,将几乎全部使用Recordset对象来对数据进行操作。
4.3.3 帖子搜索模块
如果论坛的的帖子数据量比较大的时候,用帖子列表的方式来人为的寻找某帖子显然是很浪费时间的,这时要用到帖子搜索的功能。搜索最重要的是效率,这时就需要设计搜索需要的条件,使搜索达到最大效率。如图4-1。
图4-1 帖子的搜索
在图4-1里能看出,帖子的搜索,首先是有两种搜索方式,搜索作者或搜索主题的关键字。过滤的条件是三个,论坛版块、帖子日期和帖子所在数据表(如果帖子数量大的话,是可以分不同数据表储存的)。有了这些条件可以增加搜索的效率。搜索肯定要用到SQL的Select语句,那么关键就是ASP是如何操作SQL语句的。见程序4-10。
程序4-10 帖子搜索程序(Query.asp)
Dim SearchUserID,Rs
SqlColumn = "Select Top " & Cint(Mybbs.Forum_Setting(11))*SearchMaxPageList
If stype=1 And (nSearch=2 or nSearch=3) Then
SqlColumn = SqlColumn & " BoardID,RootID,Topic,Expression,UserName,PostUserID,
DateAndTime,IsBest,LockTopic,Body,AnnounceID From "
ElseIf stype=2 And pSearch=2 Then
If IsSqlDataBase Then
SqlColumn = SqlColumn & " T1.BoardID,T1.RootID,T1.Topic,T1.Expression,
T1.UserName,T1.PostUserID,T1.DateAndTime,T1.IsBest,T1.LockTopic,
T1.Body,T1.AnnounceID From "
Else
SqlColumn = SqlColumn & " BoardID,RootID,Topic,Expression,UserName,
PostUserID,DateAndTime,IsBest,LockTopic,Body,AnnounceID From "
End If
ElseIf stype=3 Then
SqlColumn = "Select Top 50 BoardID,TopicID,Title,Expression,PostUserName,PostUserID,
DateAndtime,IsBest,LockTopic From "
SqlColumn = "Select Top 50 BoardID,rootid,topic,Expression,username,postuserid,
dateandtime,IsBest,LockTopic,Body,Announceid from "
Else
SqlColumn = SqlColumn & " BoardID,TopicID,Title,Expression,PostUserName,
PostUserID,DateAndtime,IsBest,LockTopic From "
End If
'Mybbs.Stats = template.Strings(2)
Mybbs.Stats = template.Strings(4)
If Trim(searchday)<>"" Then
Mybbs.Stats = Mybbs.Stats & Replace(template.Strings(5),"{$searchday}",
request("SearchDate"))
Else
Mybbs.Stats = Mybbs.Stats & template.Strings(6)
End If
Select Case stype
Case 1 ‘省略部分
Case 2
Select Case pSearch
Case 1 '标题
SqlColumn = SqlColumn & " dv_Topic Where "&searchboard&" "&searchday&"
Title like '%"&keyword&"%' Order By TopicID Desc"
Mybbs.Stats = Mybbs.Stats & template.Strings(10)
Case 2 '内容,SQL全文索引
If Mybbs.Forum_Setting(16)<>"0" Then
If IsSqlDataBase Then
If Trim(searchboard)="" And Trim(searchday)="" Then
SqlColumn = SqlColumn & stable & " T1 Inner Join ContainsTable("&stable&",
body,'" & keyword & "'," & Mybbs.Forum_Setting(11)*SearchMaxPageList & ")
As T2 ON T1.AnnounceID = T2.[KEY] Order By T1.AnnounceID Desc"
ElseIf Trim(searchboard)="" Then
SqlColumn = SqlColumn & stable & " T1 Inner Join ContainsTable("&stable&",
body,'" & keyword & "'," & Mybbs.Forum_Setting(11)*SearchMaxPageList & ")
As T2 ON T1.AnnounceID = T2.[KEY] Where "&Replace(Replace(searchday,
"and",""),"DateAndTime","T1.DateAndTime")&" Order By T1.AnnounceID
Desc"
ElseIf Trim(searchday)="" Then
SqlColumn = SqlColumn & stable & " T1 Inner Join ContainsTable("&stable&",
body,'" & keyword & "'," & Mybbs.Forum_Setting(11)*SearchMaxPageList & ")
As T2 ON T1.AnnounceID = T2.[KEY] Where "&Replace(Replace(searchboard,
"and",""),"BoardID","T1.BoardID")&" Order By T1.AnnounceID Desc"
Else
SqlColumn = SqlColumn & stable & " T1 Inner Join ContainsTable("&stable&",
body,'" & keyword & "'," & Mybbs.Forum_Setting(11)*SearchMaxPageList & ")
As T2 ON T1.AnnounceID = T2.[KEY] Where "&Replace(searchboard,
"BoardID","T1.BoardID")&" "&Replace(Replace(searchday,"and",""),
"DateAndTime","T1.DateAndTime")&" Order By T1.AnnounceID Desc"
End If
Else
SqlColumn = SqlColumn & stable & " Where "&searchboard&" "&searchday&"
body like '%"&keyword&"%' Order By AnnounceID Desc"
End If
Mybbs.Stats = Mybbs.Stats & template.Strings(11)
Else
Response.redirect "showerr.asp?ErrCodes=