环境
- PHP7.2
- MYSQL5.7
- NGINX1.18
- centos7
分页简介
1.为什么使用分页
- 当数据太多时,一次性取完全部数据会非常消耗性能、网络,而且使得页面不美观
2.如何实现分页
- 利用mysql的limit来实现来作分页,核心参数有两个,start与size,即开始的位置与每页显示的数量。
- sql语句:select * from 表名 limit 开始的位置,数量
3.本文的分页结构
数据准备
1.创建数据库
create database learn_test CHARSET=utf8mb4;
2.创建表
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`class` varchar(50) NOT NULL DEFAULT '' COMMENT '班级',
`score` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '分数',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.填充数据
INSERT INTO `student` (`class`, `score`)
VALUES
('一年级', 82),
('一年级', 95),
('一年级', 82),
('一年级', 20),
('二年级', 95),
('二年级', 40),
('二年级', 3),
('二年级', 60),
('二年级', 10),
('三年级', 70),
('三年级', 60),
('三年级', 40),
('三年级', 90),
('三年级', 20),
('三年级', 20),
('四年级', 100),
('四年级', 100),
('四年级', 100),
('四年级', 100);
4.蠕虫复制数据
insert into student(`class`, `score`) (SELECT `class`, `score` from student);
代码实现
<?php
header("Content-Type: text/html; charset=utf-8");
//调试函数
function dd(...$args)
{
echo "<pre>";
foreach ($args as $value) {
if (is_array($value) || is_object($value)) {
print_r($value);
} else {
echo $value;
}
}
echo "</pre>";
die;
}
//注意:该函数只是演示使用而已,请不要应用到实际项目中
function buildUri($page)
{
$url = htmlspecialchars(trim($_SERVER['PHP_SELF']));
$url = $url . '?page=' . $page;
return $url;
}
$dsn = 'mysql:host=127.0.0.1;port=3306;dbname=learn_test';
//数据库用户名
$username = 'root';
//数据库密码
$password = 'root';
//条数
$page_size = 10;
//显示页数
$show_page = 10;
//当前页的值
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
try {
$pdo = new PDO($dsn, $username, $password);
//set names utf8mb4 设置编码
$pdo->exec('set names utf8mb4');
} catch (PDOException $e) {
die('连接数据库失败,错误码为:' . $e->getCode());
}
//获取数据总数
$total_student = $pdo->prepare('select count(*) as total from student');
$total_student->execute();
//指定获取方式,将对应结果集中的每一行作为一个由列名索引的数组返回。如果结果集中包含多个名称相同的列,则PDO::FETCH_ASSOC每个列名只返回一个值
$total = $total_student->fetch(PDO::FETCH_ASSOC)['total'];
$total = (int)ceil($total / $page_size);
//判断是否有要显示分页的页面
$has_page = $total > 1;
/**** 判断page变量的合法性 S*****/
$page = $page > $total ? $total : $page;
$page = $page < 1 ? 1 : $page;
/**** 判断page变量的合法性 E*****/
/**
* 为 PDOStatement::execute() 方法准备要执行的SQL语句,SQL语句可以包含零个或多个命名(:name)或问号(?)参数标记,参数在SQL执行时会被替换。
* 你不能在 SQL 语句中同时包含命名(:name)或问号(?)参数标记,只能选择其中一种风格。
* 预处理 SQL 语句中的参数在使用PDOStatement::execute()方法时会传递真实的参数。
*/
//获取数据 注意:pdo的limit有bug,需要指定数据类型,而且limit后面跟的2个参数必须是数值类型,不然的话获取不到数据
$student = $pdo->prepare('select `id`, `class`, `score` from student limit ?,?');
$student->bindValue(1, ($page - 1) * $page_size, PDO::PARAM_INT);
$student->bindValue(2, $page_size, PDO::PARAM_INT);
$student->execute();
$student_results = $student->fetchAll(PDO::FETCH_ASSOC);
/**
*
* 释放数据库连接
* 注意:
* 连接数据成功后,返回一个 PDO 类的实例给脚本,此连接在 PDO 对象的生存周期中保持活动。
* 要想关闭连接,需要销毁对象以确保所有剩余到它的引用都被删除,可以赋一个null值给对象变量。
* 如果不明确地这么做,PHP 在脚本结束时会自动关闭连接
*/
$pdo = $total_student = $student = null;
//内容的html代码
$content_html = "<div class='content'>";
$content_html .= "<table border='1' cellspacing = '0' width= '50%' align='center'>";
$content_html .= "<tr><td>id</td><td>class</td><td>score</td></tr>";
foreach ($student_results as $student_result) {
$content_html .= "<tr>";
$content_html .= "<td>" . $student_result['id'] . "</td>";
$content_html .= "<td>" . $student_result['class'] . "</td>";
$content_html .= "<td>" . $student_result['score'] . "</td>";
$content_html .= "</tr>";
}
$content_html .= "</table>";
$content_html .= "</div>";
//分页的html代码
$page_banner_html = '';
//判断是否显示分页
if ($has_page) {
/**
* 获取左右偏移量:
* 1.$left_offset --左偏移量,$right_offset --右偏移量
* 2.$show_page - 1 表示去掉当前页这个位置
* 3.由于$show_page是偶数时不能被2整除,所以左右偏移量有大有小的(我使用左大右小的规则,当然也可以使用左小右大)
*
*/
if ($show_page % 2 === 0) {
$left_offset = (int)ceil(($show_page - 1) / 2);
$right_offset = (int)floor(($show_page - 1) / 2);
} else {
$left_offset = ($show_page - 1) / 2;
$right_offset = ($show_page - 1) / 2;
}
$start = 1;
$end = $total;
//总页数大于显示的页码个数
if ($total > $show_page) {
//如果当前页大于左偏移
if ($page > $left_offset) {
$start = $page - $left_offset;
$end = $total > $page + $right_offset ? $page + $right_offset : $total;
} else {
$start = 1;
$end = $total > $show_page ? $show_page : $total;
}
//如果当前页加上右偏移大于总页数
if ($page + $right_offset > $total) {
//减去超过的页数
$start = $start - ($page + $right_offset - $end);
}
}
$page_banner_html .= "<div class='page'>";
//上一页
if ($page > 1) {
$page_banner_html .= "<a href='" . buildUri($page - 1) . "'><上一页</a>";
}
//分页列表
for ($i = $start; $i <= $end; $i++) {
if ($page == $i) {
$page_banner_html .= "<span class='current'>$i</span>";
} else {
$page_banner_html .= "<a href='" . buildUri($i) . "'>" . $i . "</a>";
}
}
//下一页
if ($page < $total) {
$page_banner_html .= "<a href='" . buildUri($page + 1) . "'>下一页></a>";
}
}
?>
<html>
<head>
<title>模仿百度分页</title>
<meta http-equiv="Content-type" content="text/html;charset=utf-8">
<style>
body{
font-size:12px;
font-family: Verdana;
width: 100%;
}
div.page{
text-align: center;
}
div.content{
margin-bottom:40px;
}
div.page a{
cursor: pointer;
border: #0f4c82 1px solid;
text-decoration:none;
padding: 4px 20px;
margin: 5px;
}
.current{
border: #0f4c82 1px solid;
background-color: #0f4c82;
padding: 4px 20px;
margin: 5px;
color: #fff;
font-weight: bold;
}
</style>
</head>
<body>
<?php echo $content_html; ?>
<?php echo $page_banner_html; ?>
</body>
</html>
效果图
参考视频
https://www.imooc.com/learn/419
参考链接
https://www.runoob.com/php/php-pdo.html