一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

经典php分页代码与分页原理

时间:2010-07-07 编辑:简简单单 来源:一聚教程网

经典php教程分页代码与分页原理
1、前言

分页显示是一种非常常见的浏览和显示大量数据的方法,属于web编程中最常处理的事件之一。对于web编程的老手来说,编写这种代码实在是和呼吸一样自然,但是对于初学者来说,常常对这个问题摸不着头绪,因此特地撰写此文对这个问题进行详细的讲解,力求让看完这篇文章的朋友在看完以后对于分页显示的原理和实现方法有所了解。本文适合初学者阅读,所有示例代码均使用php编写。

2、原理

所谓分页显示,也就是将数据库教程中的结果集人为的分成一段一段的来显示,这里需要两个初始的参数:

每页多少条记录($pagesize)?
当前是第几页($currentpageid)?

现在只要再给我一个结果集,我就可以显示某段特定的结果出来。
至于其他的参数,比如:上一页($previouspageid)、下一页($nextpageid)、总页数($numpages)等等,都可以根据前边这几个东西得到。
mysql教程数据库为例,如果要从表内截取某段内容,sql语句可以用:select * from table limit offset, rows。看看下面一组sql语句,尝试一下发现其中的规率。

前10条记录:select * from table limit 0,10
第11至20条记录:select * from table limit 10,10
第21至30条记录:select * from table limit 20,10
……

这一组sql语句其实就是当$pagesize=10的时候取表内每一页数据的sql语句,我们可以总结出这样一个模板:

select * from table limit ($currentpageid - 1) * $pagesize, $pagesize

拿这个模板代入对应的值和上边那一组sql语句对照一下看看是不是那么回事。搞定了最重要的如何获取数据的问题以后,剩下的就仅仅是传递参数,构造合适的sql语句然后使用php从数据库内获取数据并显示了。以下我将用具体代码加以说明。

3、简单代码
请详细阅读以下代码,自己调试运行一次,最好把它修改一次,加上自己的功能,比如搜索等等。

// 建立数据库连接
$link = mysql_connect("localhost", "mysql_user", "mysql_password")
   or die("could not connect: " . mysql_error());
// 获取当前页数
if( isset($_get['page']) ){
  $page = intval( $_get['page'] );
}
else{
  $page = 1;
}
// 每页数量
$pagesize = 10;
// 获取总数据量
$sql = "select count(*) as amount from table";
$result = mysql_query($sql);
$row = mysql_fetch_row($result);
$amount = $row['amount'];
// 记算总共有多少页
if( $amount ){
  if( $amount < $page_size ){ $page_count = 1; }        //如果总数据量小于$pagesize,那么只有一页
  if( $amount % $page_size ){                 //取总数据量除以每页数的余数
    $page_count = (int)($amount / $page_size) + 1;      //如果有余数,则页数等于总数据量除以每页数的结果取整再加一
  }else{
    $page_count = $amount / $page_size;           //如果没有余数,则页数等于总数据量除以每页数的结果
  }
}
else{
  $page_count = 0;
}

// 翻页链接
$page_string = '';
if( $page == 1 ){
  $page_string .= '第一页|上一页|';
}
else{
  $page_string .= '|上一页|';
}
if( ($page == $page_count) || ($page_count == 0) ){
  $page_string .= '下一页|尾页';
}
else{
  $page_string .= '下一页|尾页';
}
// 获取数据,以二维数组格式返回结果
if( $amount ){
  $sql = "select * from table order by id desc limit ". ($page-1)*$page_size .", $page_size";
  $result = mysql_query($sql);
 
  while ( $row = mysql_fetch_row($result) ){
    $rowset[] = $row;
  }
}else{
  $rowset = array();
}
// 没有包含显示结果的代码,那不在讨论范围,只要用foreach就可以很简单的用得到的二维数组来显示结果
?>


4、oo风格代码
以下代码中的数据库连接是使用的pear db类进行处理

// filename: pager.class.php
// 分页类,这个类仅仅用于处理数据结构,不负责处理显示的工作
class pager
{
  var $pagesize;       //每页的数量
  var $currentpageid;    //当前的页数
  var $nextpageid;      //下一页
  var $previouspageid;    //上一页
  var $numpages;       //总页数
  var $numitems;       //总记录数
  var $isfirstpage;     //是否第一页
  var $islastpage;      //是否最后一页
  var $sql;         //sql查询语句
 
 function pager($option)
  {
    global $db;
    $this->_setoptions($option);
    // 总条数
    if ( !isset($this->numitems) )
    {
      $res = $db->query($this->sql);
      $this->numitems = $res->numrows();
    }
    // 总页数
    if ( $this->numitems > 0 )
    {
      if ( $this->numitems < $this->pagesize ){ $this->numpages = 1; }
      if ( $this->numitems % $this->pagesize )
      {
        $this->numpages= (int)($this->numitems / $this->pagesize) + 1;
      }
      else
      {
        $this->numpages = $this->numitems / $this->pagesize;
      }
    }
    else
    {
      $this->numpages = 0;
    }

 

    
    switch ( $this->currentpageid )
    {
      case $this->numpages == 1:
        $this->isfirstpage = true;
        $this->islastpage = true;
        break;
      case 1:
        $this->isfirstpage = true;
        $this->islastpage = false;
        break;
      case $this->numpages:
        $this->isfirstpage = false;
        $this->islastpage = true;
        break;
      default:
        $this->isfirstpage = false;
        $this->islastpage = false;
    }
   
    if ( $this->numpages > 1 )
    {
      if ( !$this->islastpage ) { $this->nextpageid = $this->currentpageid + 1; }
      if ( !$this->isfirstpage ) { $this->previouspageid = $this->currentpageid - 1; }
    }
   
    return true;
  }
 
  /***
  *
  * 返回结果集的数据库连接
  * 在结果集比较大的时候可以直接使用这个方法获得数据库连接,然后在类之外遍历,这样开销较小
  * 如果结果集不是很大,可以直接使用getpagedata的方式获取二维数组格式的结果
  * getpagedata方法也是调用本方法来获取结果的
  *
  ***/
 
  function getdatalink()
  {
    if ( $this->numitems )
    {
      global $db;
     
      $pageid = $this->currentpageid;
     
      $from = ($pageid - 1)*$this->pagesize;
      $count = $this->pagesize;
      $link = $db->limitquery($this->sql, $from, $count);  //使用pear db::limitquery方法保证数据库兼容性
     
      return $link;
    }
    else
    {
      return false;
    }
  }
 
  /***
  *
  * 以二维数组的格式返回结果集
  *
  ***/
 
  function getpagedata()
  {
    if ( $this->numitems )
    {
      if ( $res = $this->getdatalink() )
      {   
        if ( $res->numrows() )
        {
          while ( $row = $res->fetchrow() )
          {
            $result[] = $row;
          }
        }
        else
        {
          $result = array();
        }
       
        return $result;
      }
      else
      {
        return false;
      }
    }
    else
    {
      return false;
    }
  }
 
  function _setoptions($option)
  {
    $allow_options = array(
          'pagesize',
          'currentpageid',
          'sql',
          'numitems'
    );
   
    foreach ( $option as $key => $value )
    {
      if ( in_array($key, $allow_options) && ($value != null) )
      {
        $this->$key = $value;
      }
    }
   
    return true;
  }
}
?>

// filename: test_pager.php
// 这是一段简单的示例代码,前边省略了使用pear db类建立数据库连接的代码
require "pager.class.php";
if ( isset($_get['page']) )
{
  $page = (int)$_get['page'];
}
else
{
  $page = 1;
}
$sql = "select * from table order by id";
$pager_option = array(
    "sql" => $sql,
    "pagesize" => 10,
    "currentpageid" => $page
);
if ( isset($_get['numitems']) )
{
  $pager_option['numitems'] = (int)$_get['numitems'];
}
$pager = @new pager($pager_option);
$data = $pager->getpagedata();
if ( $pager->isfirstpage )
{
  $turnover = "首页|上一页|";
}
else
{
  $turnover = "首页|previouspageid."&numitems=".$pager->numitems."'>上一页|";
}
if ( $pager->islastpage )
{
  $turnover .= "下一页|尾页";
}

 

else
{
  $turnover .= "nextpageid."&numitems=".$pager->numitems."'>下一页|numpages."&numitems=".$pager->numitems."'>尾页";
}
?>

 

需要说明的地方有两个:

这个类仅仅处理数据,并不负责处理显示,因为我觉得将数据的处理和结果的显示都放到一个类里边实在是有些勉强。显示的时候情况和要求多变,不如自己根据类给出的结果处理,更好的方法是根据这个pager类继承一个自己的子类来显示不同的分页,比如显示用户分页列表可以:

class memberpager extends pager
{
  function showmemberlist()
  {
    global $db;
   
    $data = $this->getpagedata();
// 显示结果的代码
    // ......
  }
}
/// 调用
if ( isset($_get['page']) )
{
  $page = (int)$_get['page'];
}
else
{
  $page = 1;
}
$sql = "select * from members order by id";
$pager_option = array(
    "sql" => $sql,
    "pagesize" => 10,
    "currentpageid" => $page
);
if ( isset($_get['numitems']) )
{
  $pager_option['numitems'] = (int)$_get['numitems'];
}
$pager = @new memberpager($pager_option);
$pager->showmemberlist();
?>

 

第二个需要说明的地方就是不同数据库的兼容性,在不同的数据库里截获一段结果的写法是不一样的。
mysql: select * from table limit offset, rows
pgsql: select * from table limit m offset n
......
所以要在类里边获取结果的时候需要使用pear db类的limitquery方法。

ok,写完收功,希望花时间看完这些文字的你不觉得是浪费了时间。

下面我们再来看一款完整理的php分页代码吧

php+mysql分页显示示例分析
web开发是今后分布式程式开发的主流,通常的web开发都要涉及到与数据库打交道,客户端从服务器端读取通常都是以分页的形式来显示,一页一页的阅读起来既方便又美观。所以说写分页程序是web开发的一个重要组成部分,在这里,我们共同来研究分页程序的编写。

  一、分页程序的原理

  分页程序有两个非常重要的参数:每页显示几条记录($pagesize)和当前是第几页($page)。有了这两个参数就可以很方便的写出分页程序,我们以mysql数据库作为数据源,在mysql里如果要想取出表内某段特定内容可以使用的 t-sql语句:select * from table limit offset,rows来实现。这里的offset是记录偏移量,它的计算方法是offset=$pagesize*($page-1),rows是要显示的记录条数,这里就是$page。也就是说select * from table limit 10,10这条语句的意思是取出表里从第11条记录开始的20条记录。

  二、主要代码解析

$pagesize=10; //设置每一页显示的记录数
$conn=mysql_connect("localhost","root",""); //连接数据库
$rs=mysql_query("select count(*) from tb_product",$conn); //取得记录总数$rs
$myrow = mysql_fetch_array($rs);
$numrows=$myrow[0];

//计算总页数

$pages=intval($numrows/$pagesize);

//判断页数设置

if (isset($_get['page'])){
 $page=intval($_get['page']);
}
else{
 $page=1; //否则,设置为第一页
}

  三、创建用例用表mytable

create table mytable(id int not null auto_increment,news_title varchar(50),news_cont text,add_time datetime,primary key(id))

  四、完整代码

<html>
<head>
<title>php分页示例</title>
<meta http-equiv="content-type" content="text/html; charset=gb2312">
</head>

<body>
<?php
 $conn=mysql_connect("localhost","root","");
 //设定每一页显示的记录数
 $pagesize=1;
 mysql_select_db("mydata",$conn);
 //取得记录总数$rs,计算总页数用
 $rs=mysql_query("select count(*) from tb_product",$conn);
 $myrow = mysql_fetch_array($rs);
 $numrows=$myrow[0];
 //计算总页数

 $pages=intval($numrows/$pagesize);
 if ($numrows%$pagesize)
  $pages++;
 //设置页数
 if (isset($_get['page'])){
  $page=intval($_get['page']);
 }
 else{
  //设置为第一页
  $page=1;
 }
 //计算记录偏移量
 $offset=$pagesize*($page - 1);
 //读取指定记录数
 $rs=mysql_query("select * from mytable order by id desc limit $offset,$pagesize",$conn);
 if ($myrow = mysql_fetch_array($rs))
 {
  $i=0;
  ?>
  <table border="0" >
  <tr>
   <td bgcolor="#e0e0e0">
    <p align="center">标题</td>
    <td bgcolor="#e0e0e0">
    <p align="center">发布时间</td>
  </tr>
  <?php
   do {
    $i++;
    ?>
  <tr>
   <td ><?=$myrow["news_title"]?></td>
   <td ><?=$myrow["news_cont"]?></td>
  </tr>
   <?php
   }
   while ($myrow = mysql_fetch_array($rs));
    echo "</table>";
  }
  echo "<div align='center'>共有".$pages."页(".$page."/".$pages.")";
  for ($i=1;$i< $page;$i++)
   echo "<a href='fenye.php?page=".$i."'>[".$i ."]</a> ";
   echo "[".$page."]";
   for ($i=$page+1;$i<=$pages;$i++)
    echo "<a href='fenye.php?page=".$i."'>[".$i ."]</a> ";
    echo "</div>";
   ?>
  </body>
  </html>

  五、总结

  本例代码在windows2000 server+php4.4.0+mysql5.0.16上运行正常。该示例显示的分页格式是[1][2][3]…这样形式。假如想显示成"首页 上一页 下一页 尾页"这样形式,请加入以下代码:

$first=1;
$prev=$page-1;
$next=$page+1;
$last=$pages;

if ($page > 1)
{
 echo "<a href='fenye.php?page=".$first."'>首页</a> ";
 echo "<a href='fenye.php?page=".$prev."'>上一页</a> ";
}

if ($page < $pages)
{
 echo "<a href='fenye.php?page=".$next."'>下一页</a>
 echo "<a href='fenye.php?page=".$last."'>尾页</a> ";
}

  其实,写分页显示代码是很简单的,只要掌握了它的工作原理。希望这篇文章能够带给那些需要这方面程序web程序员的帮助。

热门栏目