PHP学习笔记
2009-8-25
主题:实现分页显示功能
1 要点
1.1 记事分页显示
我在QQ邮箱记事本里写了15篇记事,记事列表页面却还是没有分页,网页被拉得很长,那么我就来实现这个分页功能,主要包含三个方面:
(1)首先是一个分页器,也就是百度显示结果的那个页面的下方的“上一页、下一页”,如果只有一页,则不显示分页器
(2)其次显示出当前处于第几页,以及总共有多少页
(3)显示出当前页的所有记事
1.2 实现
1.2.1 分页器函数pager($curPage, $pageCount)
我将前两个方面的功能合起来写到了一个函数里面,这个函数有两个参数:
(1)$curPage 当前页的页号
(2)$pageCount 总页数,也就是页号的上限
1.2.1.1 如果只有1页则不显示“首页”、“上一页”、“下一页”、“尾页”这四个链接
1.2.1.2 当前页不是首页才显示“首页”和“上一页”链接,否则显示为普通文字
1.2.1.3 当前页不是尾页才显示“下一页”和“尾页”链接,否则显示为普通文字
1.2.1.4 始终只显示10个数字链接(如果总页数满10页)
(1)如果当前处在第5页以前(包含第5页),则显示1到10的数字链接
(2)如果当前页距最后一页$lastPage不到5(包含5),则显示$lastPage – 9到$lastPage的数字链接
(3)其它情况则在当前页的数字链接前面显示4个数字链接,后面显示5个数字链接
(4)当前页的数字链接显示为加粗数字,其它显示为数字链接
(5)检查最前页$firstPage和最后一页$lastPage的数值是否超过了允许的范围($firstPage < 1和$lastPage > $pageCount是非法的)
1.2.1.5 显示出当前处于第几页,以及总共有多少页
1.2.2 显示出当前页的所有记事
1.2.2.1 每一页显示5篇记事即$pageSize = 5
1.2.2.2 计算总页数$pageCount
先查询出当前用户的记事总数$noteAmount,然后判断$noteAmount % $pageSize,如果能整除则总页数为$noteAmount / $pageSize,否则为(int)($noteAmount / $pageSize) + 1
1.2.2.3 使用MySQL的LIMIT子句
根据MySQL5.1英文手册的解释,可以在SELECT语句中使用LIMIT子句限制返回的结果行数。该子句可以带一个或两个参数:
(1)如果带一个参数MAX,则将返回从第0行(即第1条记录)开始,最多包含MAX行的结果集(如果不足MAX行,则有多少行返回多少行),比如:
SELECT * FROM tbl LIMIT 10; 等价于 SELECT * FROM tbl LIMIT 0,10;
它将返回第1到10共10条记录组成的结果集。
(2)如果带两个参数OFFSET(偏移量)和MAX,则将返回从OFFSET行开始最多包含MAX行的结果集,比如:
SELECT * FROM tbl LIMIT 5,10;
它将返回第6到15共10条记录组成的结果集。
这里我将ORDER BY与LIMIT子句结合,来查询当前页的记事,那么查询语句应该是这样:
$exec = "SELECT DISTINCT *
FROM Note,CategoryInfo,UserCate,CateNote
WHERE UserCate.UserID='".$_SESSION['UserID'].
"' AND UserCate.CateID=CateNote.CateID AND CateNote.CateID=CategoryInfo.CateID
AND CateNote.NoteID=Note.NoteID ORDER BY Note.NoteCreatTime DESC LIMIT ".($curPage - 1) * $pageSize.",".$pageSize;
前面说过LIMIT子句中第0行是第1条记录且以此类推,所以当前页的第一条记录应该是第($curPage - 1) * $pageSize行,而当前页当然应该包含$pageSize篇记事。
1.2.3 效果截图
1.2.3.1 首页
1.2.3.2 第3页
1.2.3.3 尾页
2 源代码
2.1 函数pager()
//用户记事的分页器函数pager()
/*
参数说明:
1 $curPage 当前页的页号
2 $pageCount 总页数,也就是页号的上限
*/
function pager($curPage, $pageCount)
{
if($pageCount > 1)//如果只有1页则不显示“首页”、“上一页”、“下一页”、“尾页”这四个链接
{
//当前页不是首页才显示“首页”和“上一页”链接,否则显示为普通文字
if($curPage == 1)
{
echo "首页|";
echo "上一页|";
}
else
{
echo "<a href=/"myNote.php?do=list&page=1/">首页</a>|";
echo "<a href=/"myNote.php?do=list&page=".($curPage - 1)."/">上一页</a>|";
}
//设定最前一页和最后一页,始终只显示10个数字链接
if($curPage <= 5)//当前页接近首页的情况
{
$firstPage = 1;
$lastPage = 10;
}
else if($pageCount - $curPage <= 5)//当前页接近尾页的情况
{
$firstPage = $pageCount - 9;
$lastPage = $pageCount;
}
else//其它情况
{
$firstPage = $curPage - 4;
$lastPage = $curPage + 5;
}
//对最前一页和最后一页进行检查,以保证它们不会超出允许的页号范围
if($firstPage < 1)//检查最前一页
{
$firstPage = 1;
}
if($lastPage > $pageCount)//检查最后一页
{
$lastPage = $pageCount;
}
//以设定好的最前一页和最后一页作为标准,显示数字链接
for($cnt = $firstPage; $cnt <= $lastPage; ++$cnt)
{
echo " ";
if($curPage == $cnt)//当前页号显示为加粗数字
{
echo "<b>".$cnt."";
}
else//非当前页号显示为数字链接
{
echo "<a href=/"myNote.php?do=list&page=".$cnt."/">".$cnt."</a>";
}
echo " ";
}
//当前页不是尾页才显示“下一页”和“尾页”链接,否则显示为普通文字
if($curPage == $pageCount)
{
echo "|下一页|";
echo "尾页<br/>/n";
}
else
{
echo "|<a href=/"myNote.php?do=list&page=".($curPage + 1)."/">下一页</a>|";
echo "<a href=/"myNote.php?do=list&page=".($pageCount)."/">尾页</a><br/>/n";
}
}
//显示当前页号和总页数
echo "第".$curPage."页|"."共有".$pageCount."页<br/>/n";
}
2.2 显示当前页记事
include_once("include/generateDatetime.func.php");
$conn = mysql_connect("localhost", "root", "870519");
mysql_query("SET NAMES GB2312");
mysql_select_db("Notepad");
//先查询出当前用户的记事总数,如果大于0再显示列表
$exec = "SELECT COUNT(NoteID) FROM UserCate,CateNote WHERE UserCate.UserID='".$_SESSION['UserID']."' AND UserCate.CateID=CateNote.CateID";
$result = mysql_query($exec);
$row = mysql_fetch_array($result);
$noteAmount = $row[0];
if($noteAmount)//记事数目大于0则显示列表
{
echo "<div><br/>/n";
echo "<br/><br/>/n";
echo "<b>所有记事  (共".$noteAmount."篇)/n";//显示出总的记事数目
echo "<hr width=/"500/" align=/"left/"/>/n";
echo "<br/>/n";
if(isset($_GET['page']))//如果定义了$_GET['page']则将其转换为int后赋给当前页变量$curPage
{
$curPage = intval($_GET['page']);
}
else//如果没有定义$_GET['page']则显示第1页
{
$curPage = 1;
}
$pageSize = 5;//每页显示的数目
//计算总页数
if($noteAmount % $pageSize)//余数大于0
{
$pageCount = (int)($noteAmount / $pageSize) + 1;
}
else//能整除
{
$pageCount = $noteAmount / $pageSize;
}
if($curPage > $pageCount)//如果所请求的页号大于总页数,则跳到最后一页
{
$curPage = $pageCount;
}
else if($curPage < 1)//如果所请求的页号小于1,则跳到第一页
{
$curPage = 1;
}
//使用LIMIT条件查询指定范围内的记录
$exec = "SELECT DISTINCT *
FROM Note,CategoryInfo,UserCate,CateNote
WHERE UserCate.UserID='".$_SESSION['UserID'].
"' AND UserCate.CateID=CateNote.CateID AND CateNote.CateID=CategoryInfo.CateID
AND CateNote.NoteID=Note.NoteID ORDER BY Note.NoteCreatTime DESC LIMIT ".($curPage - 1) * $pageSize.",".$pageSize;
$result = mysql_query($exec);
pager($curPage, $pageCount);//调用输出分页器的函数
//输出当前页的所有记事
echo "<talbe>/n";
while($row = mysql_fetch_object($result))
{
echo "<tr>/n";
echo "<td>/n";
echo "<br/><h3><a href=/"myNote.php?do=list¬eid=".$row -> NoteID."/">".str_replace(" ", " ", $row -> NoteTitle)."</a></h3>/n";
echo "<h5>创建时间:".generateAlterableTime($row -> NoteCreatTime, time())."    分类:".$row -> CateName."</h5>/n";
echo "<font>".nl2br(str_replace(" "," ",$row -> NoteContent))."<br/><br/>/n";//函数nl2br可以将换行转换为<br/>标签输出
echo "<a href=/"myNote.php?do=list¬eid=".$row -> NoteID."/">阅读全文</a>    ";
echo "<a href=/"myNote.php?do=write¬eid=".$row -> NoteID."/">编辑</a>    ";
echo "<a href=/"myNote.php?do=del¬eid=".$row -> NoteID."/">删除</a><br/><br/>/n";
echo "</td>/n";
echo "</tr>/n";
}
echo "</table>/n";
pager($curPage, $pageCount);//调用输出分页器的函数
mysql_close();
echo "<br/></div>/n";
}
else//记事数为0则提示用户无记事
{
echo "<div><br/>/n";
echo "此分类暂无记事,<a href=/"myNote.php?do=write/">我要写一篇记事</a>/n";
echo "<br/></div>/n";
}
3 总结
一直苦恼实现分页功能时数据库查询语句该怎么写,没想到MySQL的LIMIT子句可以实现这个功能。其实一直以来使用phpMyAdmin时每天都看到了LIMIT子句(在浏览一张表时查询语句总是以“LIMIT 0,30”结尾),但就是没反应过来。
顺便说一句,参考手册真的很管用,无论是PHP的,还是MySQL的。