10-分页查询原理与实现

1、查询方式的复习以及bindColumn()的介绍

<?php
namespace _0819;

//!  查询方式
//!fetch + while
//!fetchAll + foreach
//!bindValue:值绑定到变量上
//!bindParam:引用绑定到变量上
//!bindColumn:将字段绑定到变量上

//!字段和数据表都要加反引号
// 'SELECT `id`,`name`,`email` FROM `staff`';

use PDO;
$db = new PDO('mysql:dbname=phpedu','root','root');
$sql = <<< SQL
    SELECT `id`,`name`,`sex`,`email`
    FROM `staff`;
SQL;
//sql语句对象
$stmt = $db->prepare($sql);
//执行sql
$stmt->execute();

// while,foreach,list()进行结果数组的解构,解构到变量中;
//!要在预处理对象上调用bindColumn函数
$stmt->bindColumn('id',$id);
$stmt->bindColumn('name',$name);
$stmt->bindColumn('sex',$sex);
$stmt->bindColumn('email',$email);

// 用表格进行格式化打印

$table = <<< TABLE
    <style>
        table {
            border-collapse: collapse;
            width:90%;
            min-width:360px;
            margin:30px auto;
            text-align:center;
        }
        table,th,td {
            border:1px solid #000;
            padding:5px;
        }
        table caption {
            font-size:18px;
            margin-bottom:10px;
        }
        table thead {
            background:lightcyan;
        }
        table tbody tr:hover {
            cursor:pointer;
            background:#efefef;
        }
    </style>

    <table>
    <caption>员工信息表</caption>
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>性别</th>
                <th>邮箱</th>
            </tr>
        </thead>
        <tbody>
TABLE;

//!PDO::FETCH_BOUND指获取常量:可以省的,如果出问题,再加上试试
while ($stmt->fetch(PDO::FETCH_BOUND)){
    //拼装html代码

    // !heredoc与vue不同,多行字符串中只允许出现变量,不允许出现表达式
    // 对$sex进行重写
    $sex = $sex ? '男':'女';
    $table .= <<<TR
        <tr>
            <td>$id</td>
            <td>$name</td>
            <td>$sex</td>
            <td>$email</td>
        </tr>
    TR;
    // printf('%d : %s, %d, (%s)<br>',$id,$name,$sex,$email);
}

$table .= '</tbody></table>';
echo $table;
?>

上述运行结果:

 2、分页的基本原理

# 分页原理与实现

## 1.为什么分页

1.可以限制查询的结果数量,减轻网络压力

2.分页后每次请求数据量变小,用户体检更好

---

## 2. 分页SQL

``` sql
-- 单行注释
/* 多行注释 */

--全部
SELECT * FROM `staff`;

/*
    特点:
    1.从索引0开始显示,依此类推:0,1,2,3,4,...
    2.索引与id不是一回事,例如id=20,索引可能是2
    3.如果表中有100条记录,那么索引范围:(0-99)
    4.输出所有记录,即全部数据显示在一页中,只有一页
    5.当前记录的索引,也可以叫"偏移量",sql中用"OFFSET"表示
*/

SELECT * FROM `staff` LIMIT 5 OFFSET 0;

--简写
--LIMIT 13 OFFSET 0 === LIMIT 0,13

SELECT * FROM `staff` LIMIT 0,5;
--OFFSET 0:默认,可以不写

--那如果要分页显示,只要修改偏移量就可以了

--以下是分页演示
--每页显示10条,从第1页开始(偏移量从0开始)

-- 第1页:OFFSET=0

--计算-> offset = (1-1) * 10 = 0
SELECT * FROM `staff` LIMIT 0,10;
--正在显示第 0 - 9 行 (共 10 行, 查询花费 0.0002 秒。)
--下一页的偏移量:从10开始

-- 第2页:OFFSET=10

--计算-> offset = (2-1) * 10 = 10
SELECT * FROM `staff` LIMIT 10,10;
--正在显示第 10 - 19 行 (共 10 行, 查询花费 0.0002 秒。)
--下一页的偏移量:从20开始

-- 第2页:OFFSET=20

--计算-> offset = (3-1) * 10 = 20
SELECT * FROM `staff` LIMIT 20,10;
--正在显示第 20 - 29 行 (共 10 行, 查询花费 0.0002 秒。)
--下一页的偏移量:从30开始

/**
    分析:
    1.分页查询中,变化的是起始偏移量,不变的是每页的数量
    2.数量,当前页数,和当前偏移量之间是有一定的关系的
    3.根据数量和页数,可以计算出偏移量
    4.公式 : 偏移量 = (页数-1) * 数量
 */
```
## 3.获取当前分页数据的条件

1.当前页码: `$_GET['p']`
2.当前页显示数量:`$num`
3.当前页起始偏移量:`OFFSET = (当前页码 - 1) * 显示数量`
4.SQL模板: `SELECT * FROM table_name LIMIT offset,num`

---

## 4.显示分页条需要的条件

1.总记录数:`SELECT COUNT(*) FROM table_name`;
2.总页数:`ceil(总记录数 / 每页显示数)`,结果要向上取整,确保完整性
<!-- 总页数是计算出来的,在当前的sql语句中是拿不到的 -->

---

## 5.结论

### 5.1 `三个数据是已知的`

1.当前页码
2.显示数量
3.总记录数量

### 5.2 `2个需要计算的`

1.每页起始偏移量
2.总页数

 3、获取分页条

<?php

//  * 获取分页条

namespace _0819;

use PDO;

//连接
$db = new PDO('mysql:dbname=phpedu','root','root');

//1.页数

//! ??指默认值
$page = $_GET['p'] ?? 1;
echo '当前页数 : p = '. $page . '<br>';

//2.数量
$num = 5;
echo '当前数量 : num = ' . $num . '<br>';

//3.偏移量 = (页数 - 1) * 数量
$offset = ($page - 1) * $num;
echo '当前偏移量 : offset = ' . $offset . '<br>';

// 4.计算总记录数
// SELECT CEIL(COUNT(*)/5) AS 'total' FROM `staff`;
// SELECT COUNT(*) AS 'total' FROM `staff`;

$sql = 'SELECT COUNT(*) AS `total` FROM `staff`';
$stmt = $db->prepare($sql);
$stmt->execute();

//将总数量绑定到一个变量上
$stmt->bindColumn('total',$total);
$stmt->fetch();
echo '当前总记录数量: total = ' . $total . '<br>';
//向上取整计算总页数
$pages = ceil($total/$num);
echo '当前总页数: pages = ' . $pages . '<br>'; 

$sql = <<< SQL
    SELECT * 
    FROM `staff`
    LIMIT $offset,$num;
SQL;

$stmt = $db->prepare($sql);
$stmt->execute();
$staffs = $stmt->fetchAll(PDO::FETCH_ASSOC);

echo '<hr>';
if(count($staffs) === 0){
    echo '查询结果为空';
}else{
    foreach($staffs as $staff) {
        //!extract()函数 将一个关联数组直接解析到一个变量列表中
        extract($staff);//$id,$name,$sex,$email
        printf('%d-%s-%s-%s<br>',$id,$name,$sex,$email);
    }
}
echo '<hr>';
?>

上述运行结果:

  4、分页展示数据

<?php
require 'demo3.php';
require '/page_refer.php';
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>分页展示数据</title>
    <style>
        table {
            border-collapse: collapse;
            /* width: 90%; */
            min-width: 200px;
            margin: 30px 0;
            text-align: center;
        }

        table,
        th,
        td {
            border: 1px solid #000;
            padding: 5px;
        }

        table thead {
            background-color: lightcyan;
        }

        table caption {
            font-size: larger;
            margin-bottom: 8px;
        }

        body>p {
            display: flex;
        }

        p>a {
            text-decoration: none;
            color: #555;
            border: 1px solid;
            padding: 5px 10px;
            margin: 10px 2px;
        }

        .active {
            background-color: seagreen;
            color: white;
            border: 1px solid seagreen;
        }
    </style>
</head>

<body>
    <table>
        <caption>员工信息表</caption>
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>性别</th>
                <th>邮箱</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($staffs as $staff) : extract($staff) ?>
                <tr>
                    <td><?= $id ?></td>
                    <td><?= $name ?></td>
                    <td><?= $sex ?></td>
                    <td><?= $email ?></td>
                </tr>
            <?php endforeach ?>
        </tbody>
    </table>
    <p>
        <?php for ($i = 1; $i <= $pages; $i++) : ?>
            <?php
            //页码跳转的url
            $url = $_SERVER['PHP_SELF'] . '?p=' . $i;
            //实现页码高亮
            $page = $_GET['p'] ?? 1;
            $active = ($i == $page) ? 'active':null;
            ?>
            <a href="<?=$url?>" class="<?=$active?>"><?= $i ?></a>
        <?php endfor ?>
    </p>
</body>

</html>

 上述运行结果:

   5、简洁的分页展示

<?php
require 'demo3.php';
require 'page_refer.php';

//实现页码高亮
$page = $_GET['page'] ?? 1;
$pageChange = createPages((int)$page, ceil((int)$total / 5));

function upp($a){
    next($a);
}
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="demo4.css">
    <title>分页展示数据</title>
    <style>
        table {
            border-collapse: collapse;
            /* width: 90%; */
            min-width: 200px;
            margin: 30px 0;
            text-align: center;
        }

        table,
        th,
        td {
            border: 1px solid #000;
            padding: 5px;
        }

        table thead {
            background-color: lightcyan;
        }

        table caption {
            font-size: larger;
            margin-bottom: 8px;
        }

        body>p {
            display: flex;
        }

        p>a {
            text-decoration: none;
            color: #555;
            border: 1px solid;
            padding: 5px 10px;
            margin: 10px 2px;
        }

        .active {
            background-color: seagreen;
            color: white;
            border: 1px solid seagreen;
        }
    </style>
</head>

<body>
    <table>
        <caption>员工信息表</caption>
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>性别</th>
                <th>邮箱</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($staffs as $staff) : extract($staff) ?>
                <tr>
                    <td><?= $id ?></td>
                    <td><?= $name ?></td>
                    <td><?= $sex ?></td>
                    <td><?= $email ?></td>
                </tr>
            <?php endforeach ?>
        </tbody>
    </table>
    <p>
        <?php for ($i = 1; $i <= $pages; $i++) : ?>
            <?php
            //页码跳转的url
            //$_SERVER['PHP_SELF']代表当前自己的php脚本
            $url = $_SERVER['PHP_SELF'] . '?page=' . $i;

            $active = ($i == $page) ? 'active' : null;
            ?>
            <a href="<?= $url ?>" class="<?= $active ?>"><?= $i ?></a>
        <?php endfor ?>
    </p>
    
    <p class="midPage">
        <?php $a = $_GET['page']-1;?>
        <?php if($a>0) :?>
            <?php $url2 = $_SERVER['PHP_SELF'] . '?page=' . $a;?>
            <a href="<?= $url2 ?>" class="upPage" onclick="upp($a)">上一页</a>
        <?php endif?>
        
        <?php foreach ($pageChange as $v) : ?>
            <?php if (isset($v)) : ?>
                <a href="<?php echo $_SERVER['PHP_SELF'] . '?page=' . $v ?>" 
                    <?php echo $page == $v ? 'class="active"' : null ?>
                >
                    <?= $v ?>
                </a>
            <?php else : ?>
                <a>......</a>
            <?php endif ?>
        <?php endforeach ?>

        <?php $b = $_GET['page']+1;?>
        <?php if($b<$pages) :?>
            <?php $url3 = $_SERVER['PHP_SELF'] . '?page=' . $b;?>
            <a href="<?= $url3 ?>" class="upPage">下一页</a>
        <?php endif?>
    </p>
</body>

</html>

 上述运行结果:

6、简洁的且好看的分页展示

page_refer.php

<?php

// ! 仿php.cn分页作用参考代码

/**
     * 生成分页码
     *
     * @param integer $page 当前页
     * @param integer $pages 总页数
     * @return array
     */
function createPages(int $page, int $pages): array
{
    // 当前是第8页, 共计20页
    // [1,  ...    6, 7, 8, 9, 10,  ....    20]
    // 当前是第10页, 共计20页
    // [1,  ...    8, 9, 10, 11, 12,  ....    20]

    // 1. 生成与总页数长度相同的递增的整数数组
    $pageArr = range(1, $pages);

    // 2. 只需要当前和前后二页, 其它页码用 false/null 来标记

    $paginate =  array_map(function ($p) use ($page, $pages) {
        if($page==4){
            return   ($p ==1 ||$p == $pages || abs($page-$p) <=3) ? $p : null;
        }elseif($page==3){
            return   ($p ==1 ||$p == $pages || abs($page-$p) <=4) ? $p : null;
        }elseif($page==2){
            return   ($p ==1 ||$p == $pages || abs($page-$p) <=5) ? $p : null;
        }elseif($page==1){
            return   ($p ==1 ||$p == $pages || abs($page-$p) <=6) ? $p : null;
        }else{
            return   ($p ==1 ||$p == $pages || abs($page-$p) <=2) ? $p : null;
        }
        
    }, $pageArr);

    // dump($paginate);
    // 去重, 替换
    $before = array_unique(array_slice($paginate, 0, $page));
    $after = array_unique(array_slice($paginate, $page));


    // 用解构进行合并
    return [...$before, ...$after];
}

demo3.php

<?php

//  * 获取分页条

namespace _0819;

use PDO;

//连接
$db = new PDO('mysql:dbname=phpedu','root','root');

//1.页数

//! ??指默认值
$page = $_GET['page'] ?? 1;
echo '当前页数 : p = '. $page . '<br>';

//2.数量
$num = 5;
echo '当前数量 : num = ' . $num . '<br>';

//3.偏移量 = (页数 - 1) * 数量
$offset = ($page - 1) * $num;
echo '当前偏移量 : offset = ' . $offset . '<br>';

// 4.计算总记录数
// SELECT CEIL(COUNT(*)/5) AS 'total' FROM `staff`;
// SELECT COUNT(*) AS 'total' FROM `staff`;

$sql = 'SELECT COUNT(*) AS `total` FROM `staff`';
$stmt = $db->prepare($sql);
$stmt->execute();

//将总数量绑定到一个变量上
$stmt->bindColumn('total',$total);
$stmt->fetch();
echo '当前总记录数量: total = ' . $total . '<br>';
//向上取整计算总页数
$pages = ceil($total/$num);
echo '当前总页数: pages = ' . $pages . '<br>'; 

$sql = <<< SQL
    SELECT * 
    FROM `staff`
    LIMIT $offset,$num;
SQL;

$stmt = $db->prepare($sql);
$stmt->execute();
$staffs = $stmt->fetchAll(PDO::FETCH_ASSOC);

echo '<hr>';
if(count($staffs) === 0){
    echo '查询结果为空';
}else{
    foreach($staffs as $staff) {
        //!extract()函数 将一个关联数组直接解析到一个变量列表中
        extract($staff);//$id,$name,$sex,$email
        printf('%d-%s-%s-%s<br>',$id,$name,$sex,$email);
    }
}
echo '<hr>';
?>

demo4.php

<?php
require 'demo3.php';
require 'page_refer.php';

//实现页码高亮
$page = $_GET['page'] ?? 1;
$pageChange = createPages((int)$page, ceil((int)$total / 5));

function upp($a){
    next($a);
}
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="demo4.css">
    <title>分页展示数据</title>
    <style>
        table {
            border-collapse: collapse;
            /* width: 90%; */
            min-width: 200px;
            margin: 30px 0;
            text-align: center;
        }

        table,
        th,
        td {
            border: 1px solid #000;
            padding: 5px;
        }

        table thead {
            background-color: lightcyan;
        }

        table caption {
            font-size: larger;
            margin-bottom: 8px;
        }

        body>p {
            display: flex;
        }

        p>a {
            text-decoration: none;
            color: #555;
            border: 1px solid;
            padding: 5px 10px;
            margin: 10px 2px;
        }

        .active {
            background-color: seagreen;
            color: white;
            border: 1px solid seagreen;
        }
    </style>
</head>

<body>
    <table>
        <caption>员工信息表</caption>
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>性别</th>
                <th>邮箱</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($staffs as $staff) : extract($staff) ?>
                <tr>
                    <td><?= $id ?></td>
                    <td><?= $name ?></td>
                    <td><?= $sex ?></td>
                    <td><?= $email ?></td>
                </tr>
            <?php endforeach ?>
        </tbody>
    </table>
    <p>
        <?php for ($i = 1; $i <= $pages; $i++) : ?>
            <?php
            //页码跳转的url
            //$_SERVER['PHP_SELF']代表当前自己的php脚本
            $url = $_SERVER['PHP_SELF'] . '?page=' . $i;

            $active = ($i == $page) ? 'active' : null;
            ?>
            <a href="<?= $url ?>" class="<?= $active ?>"><?= $i ?></a>
        <?php endfor ?>
    </p>
    
    <p class="midPage">
        <?php $a = $_GET['page']-1;?>
        <?php if($a>0) :?>
            <?php $url2 = $_SERVER['PHP_SELF'] . '?page=' . $a;?>
            <a href="<?= $url2 ?>">上一页</a>
        <?php endif?>
        
        <?php foreach ($pageChange as $v) : ?>
            <?php if (isset($v)) : ?>
                <a href="<?php echo $_SERVER['PHP_SELF'] . '?page=' . $v ?>" 
                    <?php echo $page == $v ? 'class="active"' : null ?>
                >
                    <?= $v ?>
                </a>
            <?php else : ?>
                <a>......</a>
            <?php endif ?>
        <?php endforeach ?>

        <?php $b = $_GET['page']+1;?>
        <?php if($b<= $pages) :?>
            <?php $url3 = $_SERVER['PHP_SELF'] . '?page=' . $b;?>
            <a href="<?= $url3 ?>">下一页</a>
        <?php endif?>
    </p>
</body>

</html>

上述运行结果:

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七色的天空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值