服务端 - PHP - 分页
一、原理
- 分页技术核心在于确定当前的页数,然后利用 SQL查询中 的 LIMIT 关键字来指定输出对应的记录数
- 首先确定每页要输出多少条记录,假定是输出10条
- 得出每一页的索引范围(结果数组中的索引范围):假如当前是第1页,那么就是0,9(LIMIT 0,10、LIMIT 10 OFFSET 0);第2页是10,19(LIMIT 10,10、LIMIT 10 OFFSET 10);第3页是20,29(LIMIT 20,10、LIMIT 10 OFFSET 20),以此类推
- 得出计算每一页的偏移量(起始索引)的公式:(当前页 - 1) * 每页显示的记录数
三、实现
1. 简单分页
<?php require 'handle2.php'; ?>
<!DOCTYPE html>
<html lang="zh_hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>分页</title>
<link rel="stylesheet" href="css/index1.css">
</head>
<body>
<table>
<caption>用户信息表</caption>
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>性别</th>
<th>Email</th>
<th>注册时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!--遍历并渲染数据-->
<?php foreach ($staffs as $staff): ?>
<tr>
<td><?php echo $staff['id'] ?></td>
<td><?php echo $staff['user_name'] ?></td>
<td><?php echo $staff['sex'] ?></td>
<td><?php echo $staff['email'] ?></td>
<td><?php echo date('Y-m-d', $staff['reg_time']) ?></td>
<td><button>编辑</button><button>删除</button></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<!--根据总页数渲染分页条数据-->
<p>
<?php for ($i=1; $i<=$pages; $i++): ?>
<?php
$jump = sprintf('%s?p=%s', $_SERVER['PHP_SELF'], $i);
$active = ($i == $page) ? 'active' : null;
?>
<!--jump为跳转按钮,用来设置当前页-->
<!--active用来设置类名应用样式-->
<!--i用来设置页码名称-->
<a href="<?php echo $jump ?>" class="<?php echo $active ?>"><?php echo $i ?></a>
<?php endfor ?>
</p>
</body>
</html>
<?php
//连接数据库
$pdo = new PDO('mysql:host=localhost;dbname=shopping', 'root', 'root');
//1. 定义每页显示的记录数
$n = 10;
//2. 获取总页数
$sql = "SELECT CEIL(COUNT(`id`)/{$n}) AS `total` FROM `userinfo`";
$pages = $pdo->query($sql)->fetch()['total'];
//3. 定义当前的页码,默认值是1
$page = $_GET['p'] ?? 1;
//4. 获取偏移量
$p_start = $n * ($page - 1);
//5. 获取分页数据
$sql = "SELECT * FROM `userinfo` LIMIT {$n} OFFSET {$p_start}";
$staffs = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
2. 带有跳转到首页, 前一页, 下一页, 尾页的功能
<p>
<!--首页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=1' ?>">首页</a>
<!--前一页-->
<?php
//前一页=当前页-1
$prev = $page - 1;
//如果当前页等于1,那么前一页也等于1,防止出现负页数
if ($page == 1) $prev = 1;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $prev ?>">向上</a>
<!--根据总页数渲染分页条数据-->
<?php for ($i=1; $i<=$pages; $i++): ?>
<?php
$jump = sprintf('%s?p=%s', $_SERVER['PHP_SELF'], $i);
$active = ($i == $page) ? 'active' : null;
?>
<!--jump为跳转按钮,用来设置当前页-->
<!--active用来设置类名应用样式-->
<!--i用来设置页码名称-->
<a href="<?php echo $jump ?>" class="<?php echo $active ?>"><?php echo $i ?></a>
<?php endfor ?>
<!--下一页-->
<?php
//下一页=当前页+1
$next = $page + 1;
//如果当前页等于总页数,那么下一页等于总页数,防止出现无线递增的页数
if ($page == $pages) $next = $pages;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $next ?>">向下</a>
<!--尾页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $pages ?>">尾页</a>
</p>
3. 带有页码省略功能(自定义偏移量,不需要计算公式)
- 分页技术核心在于在确定分页条的偏移量情况下,如何计算起始页及终止页,以及如何解决自定义分页条页码数大于总页数时页码无限递增的bug
<p>
<!--页码省略功能-->
<?php
//自定义分页条页码数
$show_pages = 7;
//自定义分页条偏移量
$offset_page = 3;
//分页条起始页
$start_page = 1;
//分页条终止页
$end_page = $pages;
// 只有当前分页条数量 < 总页数, 才有必要显示出省略标记
if ($start_page < $pages) {
//1. 如果当前页大于偏移量+1,则在起始显示...
if ($page > ($offset_page + 1)) $start_omit = '...';
//2. 重置分页条页码
if ($page > $offset_page) {
//起始页=当前页-偏移量
$start_page = $page - $offset_page;
//终止页=当前页+偏移量
$end_page = $page + $offset_page;
} else {
//默认起始页是1,终止页等于自定义分页条页码数
$start_page = 1;
$end_page = $show_pages;
}
//3. 当当前页+偏移量大于总页数时终止页等于总页数,防止出现自定义分页条页码数大于总页数时页码无限递增的bug
if ($page + $offset_page > $pages) {
$end_page = $pages;
}
//4. 如果当前页大于偏移量+1和当前页加偏移量小于总页数,则在末尾显示...
if ($page > ($offset_page + 1) && $show_pages < $pages && $page + $offset_page < $pages) $end_omit = '...';
}
?>
<!--首页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=1' ?>">首页</a>
<!--前一页-->
<?php
//前一页=当前页-1
$prev = $page - 1;
//如果当前页等于1,那么前一页也等于1,防止出现负页数
if ($page == 1) $prev = 1;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $prev ?>">向上</a>
<!--前置省略号-->
<?php if (isset($start_omit)): ?><a href="#"><?php echo $start_omit ?></a><?php endif ?>
<!--根据总页数渲染分页条数据-->
<!--将起始页和总页码置换-->
<?php for ($i=$start_page; $i<=$end_page; $i++): ?>
<?php
$jump = sprintf('%s?p=%s', $_SERVER['PHP_SELF'], $i);
$active = ($i == $page) ? 'active' : null;
?>
<!--jump为跳转按钮,用来设置当前页-->
<!--active用来设置类名应用样式-->
<!--i用来设置页码名称-->
<a href="<?php echo $jump ?>" class="<?php echo $active ?>"><?php echo $i ?></a>
<?php endfor ?>
<!--后置省略号-->
<?php if (isset($end_omit)): ?><a href="#"><?php echo $end_omit ?></a><?php endif ?>
<!--下一页-->
<?php
//下一页=当前页+1
$next = $page + 1;
//如果当前页等于总页数,那么下一页等于总页数,防止出现无线递增的页数
if ($page == $pages) $next = $pages;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $next ?>">向下</a>
<!--尾页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $pages ?>">尾页</a>
</p>
4. 带有显示起始和末尾页码功能
<p>
<!--页码省略功能-->
<?php
//自定义分页条页码数
$show_pages = 5;
//自定义分页条偏移量
$offset_page = 2;
//分页条起始页
$start_page = 1;
//分页条终止页
$end_page = $pages;
//倒数第二页
$n = $pages - 1;
// 只有当前分页条数量 < 总页数, 才有必要显示出省略标记
if ($start_page < $pages) {
//1. 如果当前页大于偏移量+1,则在起始显示...
if ($page > ($offset_page + 1)) {
$start_omit = '...';
}
//2. 重置分页条页码
if ($page > $offset_page) {
//起始页=当前页-偏移量
$start_page = $page - $offset_page;
//终止页=当前页+偏移量
$end_page = $page + $offset_page;
} else {
//默认起始页是1,终止页等于自定义分页条页码数
$start_page = 1;
$end_page = $show_pages;
}
//3. 当当前页+偏移量大于总页数时终止页等于总页数,防止出现自定义分页条页码数大于总页数时页码无限递增的bug
if ($page + $offset_page > $pages) {
$end_page = $pages;
}
//4. 如果当前页大于偏移量+1和当前页加偏移量小于总页数,则在末尾显示...
if ($page > ($offset_page + 1) && $show_pages < $pages && $page + $offset_page < $pages) $end_omit = '...';
}
?>
<!--首页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=1' ?>">首页</a>
<!--前一页-->
<?php
//前一页=当前页-1
$prev = $page - 1;
//如果当前页等于1,那么前一页也等于1,防止出现负页数
if ($page == 1) $prev = 1;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $prev ?>">向上</a>
<!--前二页-->
<?php if ($page > ($offset_page + 1)): ?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=1' ?>">1</a>
<?php endif ?>
<?php if ($page > ($offset_page + 2)): ?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=2' ?>">2</a>
<?php endif ?>
<!--前置省略号-->
<?php if (isset($start_omit)): ?><a href="#"><?php echo $start_omit ?></a><?php endif ?>
<!--根据总页数渲染分页条数据-->
<!--将起始页和总页码置换-->
<?php for ($i=$start_page; $i<=$end_page; $i++): ?>
<?php
$jump = sprintf('%s?p=%s', $_SERVER['PHP_SELF'], $i);
$active = ($i == $page) ? 'active' : null;
?>
<!--jump为跳转按钮,用来设置当前页-->
<!--active用来设置类名应用样式-->
<!--i用来设置页码名称-->
<a href="<?php echo $jump ?>" class="<?php echo $active ?>"><?php echo $i ?></a>
<?php endfor ?>
<!--后置省略号-->
<?php if (isset($end_omit)): ?><a href="#"><?php echo $end_omit ?></a><?php endif ?>
<!--后二页-->
<?php if ($page > ($offset_page + 2) && ($page + $offset_page) < $n): ?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $n ?>"><?php echo $n ?></a>
<?php endif ?>
<?php if ($page > ($offset_page + 1) && ($page + $offset_page) < $pages): ?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $pages ?>"><?php echo $pages ?></a>
<?php endif ?>
<!--下一页-->
<?php
//下一页=当前页+1
$next = $page + 1;
//如果当前页等于总页数,那么下一页等于总页数,防止出现无线递增的页数
if ($page == $pages) $next = $pages;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $next ?>">向下</a>
<!--尾页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $pages ?>">尾页</a>
</p>
5. 带有记录的编辑和删除功能
<?php require 'handle2.php'; ?>
<!DOCTYPE html>
<html lang="zh_hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>分页</title>
<link rel="stylesheet" href="css/index1.css">
</head>
<body>
<table>
<caption>用户信息表</caption>
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>性别</th>
<th>Email</th>
<th>注册时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!--遍历并渲染数据-->
<?php foreach ($staffs as $staff): ?>
<tr>
<td><?php echo $staff['id'] ?></td>
<td><?php echo $staff['user_name'] ?></td>
<td><?php echo $staff['sex'] ?></td>
<td><?php echo $staff['email'] ?></td>
<td><?php echo date('Y-m-d', $staff['reg_time']) ?></td>
<td><button onclick="location.href='handle3.php?action=edit&id=<?php echo $staff['id']?>'">编辑</button>
<button onclick="del(<?php echo $staff['id']?>)">删除</button></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<p>
<!--页码省略功能-->
<?php
//自定义分页条页码数
$show_pages = 5;
//自定义分页条偏移量
$offset_page = 2;
//分页条起始页
$start_page = 1;
//分页条终止页
$end_page = $pages;
//倒数第二页
$n = $pages - 1;
// 只有当前分页条数量 < 总页数, 才有必要显示出省略标记
if ($start_page < $pages) {
//1. 如果当前页大于偏移量+1,则在起始显示...
if ($page > ($offset_page + 1)) {
$start_omit = '...';
}
//2. 重置分页条页码
if ($page > $offset_page) {
//起始页=当前页-偏移量
$start_page = $page - $offset_page;
//终止页=当前页+偏移量
$end_page = $page + $offset_page;
} else {
//默认起始页是1,终止页等于自定义分页条页码数
$start_page = 1;
$end_page = $show_pages;
}
//3. 当当前页+偏移量大于总页数时终止页等于总页数,防止出现自定义分页条页码数大于总页数时页码无限递增的bug
if ($page + $offset_page > $pages) {
$end_page = $pages;
}
//4. 如果当前页大于偏移量+1和当前页加偏移量小于总页数,则在末尾显示...
if ($page > ($offset_page + 1) && $show_pages < $pages && $page + $offset_page < $pages) $end_omit = '...';
}
?>
<!--首页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=1' ?>">首页</a>
<!--前一页-->
<?php
//前一页=当前页-1
$prev = $page - 1;
//如果当前页等于1,那么前一页也等于1,防止出现负页数
if ($page == 1) $prev = 1;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $prev ?>">向上</a>
<!--前二页-->
<?php if ($page > ($offset_page + 1)): ?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=1' ?>">1</a>
<?php endif ?>
<?php if ($page > ($offset_page + 2)): ?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=2' ?>">2</a>
<?php endif ?>
<!--前置省略号-->
<?php if (isset($start_omit)): ?><a href="#"><?php echo $start_omit ?></a><?php endif ?>
<!--根据总页数渲染分页条数据-->
<!--将起始页和总页码置换-->
<?php for ($i=$start_page; $i<=$end_page; $i++): ?>
<?php
$jump = sprintf('%s?p=%s', $_SERVER['PHP_SELF'], $i);
$active = ($i == $page) ? 'active' : null;
?>
<!--jump为跳转按钮,用来设置当前页-->
<!--active用来设置类名应用样式-->
<!--i用来设置页码名称-->
<a href="<?php echo $jump ?>" class="<?php echo $active ?>"><?php echo $i ?></a>
<?php endfor ?>
<!--后置省略号-->
<?php if (isset($end_omit)): ?><a href="#"><?php echo $end_omit ?></a><?php endif ?>
<!--后二页-->
<?php if ($page > ($offset_page + 2) && ($page + $offset_page) < $n): ?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $n ?>"><?php echo $n ?></a>
<?php endif ?>
<?php if ($page > ($offset_page + 1) && ($page + $offset_page) < $pages): ?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $pages ?>"><?php echo $pages ?></a>
<?php endif ?>
<!--下一页-->
<?php
//下一页=当前页+1
$next = $page + 1;
//如果当前页等于总页数,那么下一页等于总页数,防止出现无线递增的页数
if ($page == $pages) $next = $pages;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $next ?>">向下</a>
<!--尾页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $pages ?>">尾页</a>
</p>
<!--删除记录前弹出确认框-->
<script>
function del(id) {
return confirm('是否删除?') ? location.href='handle3.php?action=del&id='+id : false;
}
</script>
</body>
</html>
<?php
//获取要被编辑的员工的数据
$staff = $pdo->query("SELECT * FROM `userinfo` WHERE `id`={$id}")->fetch(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="zh_hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>注册页</title>
<link rel="stylesheet" href="\css\edit.css">
</head>
<body>
<h2>编辑表单</h2>
<div class="f-box">
<form action="<?php echo $_SERVER['PHP_SELF'].'?action=doedit&id='.$id ?>"" method="POST">
<fieldset>
<div class="d-box">
<label for="username">姓名:</label>
<input type="text" name="username" id="username" value="<?php echo $staff['user_name'] ?>">
</div>
<div class="d-box">
<label for="sex">性别:</label>
<input type="radio" name="sex" id="sex" value="1" <?php if ($staff['sex'] == '男') echo 'checked' ?>><label for="">男</label>
<input type="radio" name="sex" id="sex" value="2" <?php if ($staff['sex'] == '女') echo 'checked' ?>><label for="">女</label>
<input type="radio" name="sex" id="sex" value="3" <?php if ($staff['sex'] == '保密') echo 'checked' ?>><label for="">保密</label>
</div>
<div class="d-box">
<label for="email">邮箱:</label>
<input type="email" name="email" id="email" value="<?php echo $staff['email'] ?>">
</div>
<div class="d-box">
<label for="reg_time">注册时间:</label>
<input type="date" name="reg_time" id="reg_time" value="<?php echo date('Y-m-d', $staff['reg_time']) ?>">
</div>
<input type="hidden" name="id" id="id" value="<?php echo $staff['id'] ?>">
<div class="d-box">
<button type="submit">保存</button>
</div>
</fieldset>
</form>
</div>
</body>
</html>
<?php
//获取分页数据
require 'handle2.php';
//获取方法值
$action =$_GET['action'];
//获取id值
$id = $_GET['id'];
//根据方法值来执行相应的方法
switch ($action) {
//1. 渲染编辑表单
case 'edit':
include './user/edit.php';
break;
//2. 执行编辑操作
case 'doedit':
$sql = 'UPDATE `userinfo` SET `user_name`=:username, `sex`=:sex, `email`=:email, `reg_time`=:reg_time WHERE `id`=:id';
$_POST['reg_time'] = strtotime($_POST['reg_time']);
$stmt = $pdo->prepare($sql);
$stmt->execute($_POST);
if ($stmt->rowCount() === 1) echo '<script>alert("更新成功");location.href="./index.php"</script>';
break;
//3. 执行删除操作
case 'del':
$stmt = $pdo->query("DELETE FROM `userinfo` WHERE `id`=$id;");
if ($stmt->rowCount() === 1) echo '<script>alert("删除成功");location.href="./index.php"</script>';
break;
}
四、课程总结
- 今天学习了 PHP 的分页,通过上课认真听讲和认真完成老师布置的作业,使得我对 PHP 分页技术的理解和运用更加深入和熟悉。最主要的知识点是明白和掌握了分页技术的特点以及它的基本用法。