PHP分页原理是怎么样的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP分页原理是怎么样的相关的知识,希望对你有一定的参考价值。

有谁可以介绍一下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、简单代码
请详细阅读以下代码,自己调试运行一次,最好把它修改一次,加上自己的功能,比如搜索等等。

<?php
// 建立数据库连接
$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 .= '<a href="/?page=1>";第一页</a>|<a href="/?page='."($page-1).'>上一页</a>|';

if( ($page == $page_count) || ($page_count == 0) )
$page_string .= '下一页|尾页';

else
$page_string .= '<a href="/?page='."($page+1).'>下一页</a>|<a href="/?page='."$page_count.'>尾页</a>';

// 获取数据,以二维数组格式返回结果
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类进行处理

<?php
// 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;


?>

<?php
// 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 = "<a href='?page=1&numItems=".$pager->numItems."'>首页</a>|<a href="/?page=".$pager->PreviousPageID."&numItems=".$pager->numItems."'>上一页</a>|";

if ( $pager->isLastPage )

$turnover .= "下一页|尾页";

else

$turnover .= "<a href="/?page=".$pager->NextPageID."&numItems=".$pager->numItems."'>下一页</a>|<a href="/?page=".$pager->numPages."&numItems=".$pager->numItems."'>尾页</a>";

?>

需要说明的地方有两个:

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

<?php
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,写完收功,希望花时间看完这些文字的你不觉得是浪费了时间。
参考技术A 我的理解是:设置好每页显示多少条,然后将查询的条件存储到变量中,然后下一页按钮中调用到这个变量,也就是说让查询的条件不丢失即可。

PHP+mysql分页原理实现

功能简介:包含上一页、下一页、首页、尾页、跳转页面等功能。

  编码寄语:化繁为简,则豁然开朗。

  运行截图:

  技术图片

  关键步骤:

  1. 创建数据库
    技术图片
    CREATE TABLE `page` (
      `ID` int(10) NOT NULL AUTO_INCREMENT,
      `NAME` varchar(10) DEFAULT NULL,
       PRIMARY KEY (`ID`) 
    ) 
    技术图片
  2. 传入页码:使用get方法
    $page=$_GET[‘p‘];
  3. 根据页码显示数据:设置每页显示数量为pageSize,页码为page,则第page页显示的第一条数据ID为:(page-1)* pagesize 。SQL语句如下
    $sql="SELECT * FROM page order by id ASC LIMIT ".($page-1)*$pageSize .",{$pageSize}";
  4. 显示数据
    技术图片
    $result=mysqli_query($conn,$sql);
        //将数据显示到table中,并为table设置格式
        echo "<div class=‘content‘>";
        echo "<table border=1 cellspacing=0 width=30% align=center>";
        echo "<tr><td>ID</td><td>NAME</td></tr>";
        while ($row = mysqli_fetch_assoc($result)) {
             echo "<tr>";
             echo "<td>{$row[‘ID‘]}</td>";
             echo "<td>{$row[‘NAME‘]}</td>";
             echo "<tr>";
        }
        echo "</table>";
        echo "</div>";
        //释放结果
        mysqli_free_result($result);
    技术图片
  5. 实现上一页、下一页功能
    $page_banner = "<a href=‘".$_SERVER[‘PHP_SELF‘]."?p=" .($page-1) . "‘><上一页</a>";
    $page_banner .= "<a href=‘".$_SERVER[‘PHP_SELF‘]."?p=" .($page+1) . "‘><下一页</a>";

    知识补充:$page_banner .= 作用是衔接;$_SERVER[‘PHP_SELF‘]表示当前正在执行的脚本的文件名。

  6. 以上四个步骤可以实现简单的分页效果。但page的值只能在地址栏手动输入更改,才能达到分页的效果。如地址栏输入:http://localhost/mypage.php?p=5  表示当前显示的是第五页。
  7. 完善阶段:page值通过页码栏获取;首页、尾页、跳转功能的实现;界面美化。
  8. 完整代码如下:mypage.php
    技术图片
    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-type" content="text/html;charset=utf-8">
    </head>
    <style type="text/css">
        body{
            font-size: 12px;font-family: verdana;width: 100%;
        }
        div.page{
            text-align: center;
        }
        div.content{
            height: 300px;
        }
        div.page a{
            border:#aaaadd 1px solid;text-decoration: none;padding: 2px 5px 2px 5px;margin: 2px;
        }
        div.page span.current{
            border:#000099 1px solid;background-color: #000099;padding: 2px 5px 2px 5px;margin: 2px;color: #fff;font-weight: bold;
        } 
        div.page span.disable{
            border:#eee 1px solid;padding:2px 5px 2px 5px; margin: 2px;color:#ddd;
        }
        div.page form{
            display: inline;
        }
    </style>
    <body>
    <?php
        //设置级别错误,通知类除外
        error_reporting(‘E_ALL&~E_NOTICE‘);  
        /**1---传入页码,使用GET获取**/
        $page=$_GET[‘p‘];
        /**2---根据页码取出数据:php->mysql处理**/
        $host="localhost";
        $username="root";
        $password="";
        $db="test";
        $pageSize=10;
        $showPage=5; 
        //连接数据库,面向过程
        $conn=mysqli_connect($host,$username,$password);
        if(!$conn){
            echo "数据库连接失败";
            exit;
        }
        //选择所要操作的数据库
        mysqli_select_db($conn,$db);
        //设置数据库编码格式
        mysqli_query($conn,"SET NAMES UTF8");
        //编写sql获取分页数据 SELECT * FROM 表名 LIMIT 起始位置,显示条数
        $sql="SELECT * FROM page order by id ASC LIMIT ".($page-1)*$pageSize .",{$pageSize}";
        //把sql语句传送到数据库
        $result=mysqli_query($conn,$sql);
        //将数据显示到table中,并未table设置格式
        echo "<div class=‘content‘>";
        echo "<table border=1 cellspacing=0 width=30% align=center>";
        echo "<tr><td>ID</td><td>NAME</td></tr>";
        while ($row = mysqli_fetch_assoc($result)) {
             echo "<tr>";
             echo "<td>{$row[‘ID‘]}</td>";
             echo "<td>{$row[‘NAME‘]}</td>";
             echo "<tr>";
        }
        echo "</table>";
        echo "</div>";
        //释放结果
        mysqli_free_result($result);
        //获取数据总条数
        $total_sql="SELECT COUNT(*)FROM page";
        $total_result=mysqli_fetch_array(mysqli_query($conn,$total_sql));
        $total=$total_result[0];
        $total_pages=ceil($total/$pageSize);
        //关闭数据库
        mysqli_close($conn);
        /**3---显示数据+显示分页条**/
        $page_banner="<div class=‘page‘>";
        //计算偏移量
        $pageoffset=($showPage-1)/2;
        //两种情况下 首页、上一页 的显示效果
        if($page>1){
            $page_banner .= "<a href=‘".$_SERVER[‘PHP_SELF‘]."?p=1‘>首页</a>";
            $page_banner .= "<a href=‘".$_SERVER[‘PHP_SELF‘]."?p=" .($page-1) . "‘><上一页</a>";
        }else{
            $page_banner .="<span class=‘disable‘>首页</span>";
            $page_banner .="<span class=‘disable‘><上一页</span>";
        }
        //显示
        $start=1;
        $end=$total_pages;
        //当总条数大于分页数时
        if($total_pages>$showPage){
            if($page>$pageoffset+1){
                $page_banner .="...";
            }
            if($page>$pageoffset){
                $start=$page-$pageoffset;
                $end=$total_pages>$page+$pageoffset?$page+$pageoffset:$total_pages;//三段式
            }
            //最前面几个特殊页号的显示。当前指的是页号1或者2时
            else{
                $start=1;
                $end=$showPage;
            }
            //最后面几个特殊页号的显示,当前显示的是页号7和8
            if($page+$pageoffset>$total_pages){
                $start=$start-($page+$pageoffset-$end);//注意理解这一句
            }
        }
        //显示页码
        for($i=$start;$i<=$end;$i++){
            //当前页页码上显示背景色
            if($page==$i){
                $page_banner .="<span class=‘current‘>{$i}</span>";
            }
            //非当前页码显示
            else{
                $page_banner .= "<a href=‘".$_SERVER[‘PHP_SELF‘]."?p=" .$i . "‘>{$i}</a>";    
            }    
        }
        if($total_pages>$showPage&&$total_pages>$page+$pageoffset){
            $page_banner .="...";    
        }
        //两种情况下的尾页、下一页 的显示效果
        if($page<$total_pages){
            $page_banner .= "<a href=‘".$_SERVER[‘PHP_SELF‘]."?p=" .($page+1) . "‘>下一页></a>";
            $page_banner .= "<a href=‘".$_SERVER[‘PHP_SELF‘]."?p=$total_pages‘>尾页</a>";
        }else{
            $page_banner .="<span class=‘disable‘>尾页</span>";
            $page_banner .="<span class=‘disable‘>下一页></span>";
        }
        $page_banner .= "共{$total_pages}页,";
        $page_banner .= "<form action=‘mypage.php‘ method=‘get‘>";
        $page_banner .= " 到第<input type=‘text‘ size=2 value=‘1‘ name=‘p‘>页";
        $page_banner .= "<input type=‘submit‘ value=‘确定‘>";
        $page_banner .= "</form>";
        $page_banner .= "</div>";
        echo $page_banner;
    ?>
    </body>
    </html>   
    技术图片

以上是关于PHP分页原理是怎么样的的主要内容,如果未能解决你的问题,请参考以下文章

PHP 带省略号的分页程序,原理是啥? 分页程序我已经写出来了,但是那个省略号 算法 和原理没弄懂

php中的分页显示

php 新闻内容显示页面分页怎么写?

php怎么分页显示mysql数据库中的记录?php分页时提示数据未定义改怎么解决?

layui分页怎么配合php使用

在php里面用ajax怎么做分页