1、PHP分页实战
- 实战分为5个文件演示:
No | 文件名称 | 备注 |
---|---|---|
1 | config.php | 连接数据+分页变量+分页函数 |
2 | edit.php | 更新表单 |
3 | handle.php | 控制删除/更新操作 |
4 | list.php | 分页列表 |
5 | sytle.css | 简单样式表 |
1.1 config.php
// PDO连接数据库
$pdo = new PDO('mysql:host=localhost;dbname=php_pro', 'root', 'root');
// 设置结果默认获取方式: 关联数组
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// 获取分页数据, 一定要知道的二个数据
// 1. 每页显示的数量
$num = 15;
// 2. 当前页码,默认为1
$page = $_GET['p'] ?? 1;
// 3. 计算每一页的第一条记录的显示偏移量
$offset = ($page - 1) * $num;
// 定义查询条件
$where='`id` >= 1';
// 4. 获取分页数据
// SElECT * FROM `table_name `LIMIT n OFFSET m;
$sql = "SELECT * FROM `users` WHERE $where LIMIT {$num} OFFSET {$offset}";
// 简写
// $sql = "SELECT * FROM `users` LIMIT {$offset}, {$num}";
$users = $pdo->query($sql)->fetchAll();
// print_r($users);
// 计算总页数
// 计算表中共计有多少条记录?
// 每一页显示几条? 5
// 总页数 = ceil(记录总数 / 每页的记录数)
$sql = "SELECT CEIL(COUNT(`id`)/{$num}) AS `total` FROM `users` WHERE $where";
// 计算总页数
$pages = $pdo->query($sql)->fetch()['total'];
function showPage($pages,$page){
$prev = ($page == 1) ? 1 : $page - 1;
$next = (($page + 1)>= $pages) ? $pages : $page + 1;
if($pages<10){
//总页码小于10页(上一页 1 2 3 4 5 6 7 8 9 下一页)
$show_page = "<a href='?p={$prev}'>上一页</a>";
for ($i= 1; $i <= $pages; $i++) {
$active = ($i == $page) ? 'active' : null;
if($i<=$pages){
$show_page.="<a href='?p=$i' class='$active'>$i</a>";
}
}
$show_page.="<a href='?p=$next'>下一页</a>";
echo $show_page;
}elseif($page <= 6){
//当前页码小于等于8页 (上一页 1 2 3 4 5 6 7 8 ... 9 10 下一页)
$show_page = "<a href='?p={$prev}'>上一页</a>";
for ($i= 1; $i <= 8; $i++) {
$active = ($i == $page) ? 'active' : null;
if($i<=$pages){
$show_page.="<a href='?p=$i' class='$active'>$i</a>";
}
}
$show_page.="<a href='javascript:;'>...</a>";
$a=$pages-1;
$show_page.="<a href='?p=$a'>$a</a>";
$show_page.="<a href='?p=$pages'>$pages</a>";
$show_page.="<a href='?p=$next'>下一页</a>";
echo $show_page;
}elseif($page<=$pages-6){
//当前页码小于等于(总页数-6)(上一页 1 2 ... 7 8 9 10 11 ... 99 100 下一页)
$show_page = "<a href='?p={$prev}'>上一页</a>";
$show_page.="<a href='?p=1'>1</a>";
$show_page.="<a href='?p=2'>2</a>";
$show_page.="<a href='javascript:;'>...</a>";
for ($i= $page-2; $i < $page+3; $i++) {
$active = ($i == $page) ? 'active' : null;
if($i<=$pages){
$show_page.="<a href='?p=$i' class='$active'>$i</a>";
}
}
$show_page.="<a href='javascript:;'>...</a>";
$a=$pages-1;
$show_page.="<a href='?p=$a'>$a</a>";
$show_page.="<a href='?p=$pages'>$pages</a>";
$show_page.="<a href='?p=$next'>下一页</a>";
echo $show_page;
}else{
//当前页码>$pages-6 (上一页 1 2 ... 94 95 96 97 98 99 100 下一页)
$show_page = "<a href='?p={$prev}'>上一页</a>";
$show_page.="<a href='?p=1'>1</a>";
$show_page.="<a href='?p=2'>2</a>";
$show_page.="<a href='javascript:;'>...</a>";
for ($i= $pages-7; $i <= $pages; $i++) {
$active = ($i == $page) ? 'active' : null;
if($i<=$pages){
$show_page.="<a href='?p=$i' class='$active'>$i</a>";
}
}
$show_page.="<a href='?p=$next'>下一页</a>";
echo $show_page;
}
}
1.2 eidt.php
<?php
// 获取要被编辑的数据
$user = $pdo->query("SELECT * FROM `users` WHERE `id`={$id}")->fetch();
// print_r($user);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户编辑</title>
</head>
<body>
<h3>用户编辑</h3>
<form action="<? echo $_SERVER['PHP_SELF']. '?action=doedit&id='.$id?>" method="POST">
<p>
<label for="username">用户名:</label>
<input type="text" name="username" id="username" value="<?=$user['username']?>">
</p>
<p>
<label for="email">邮箱:</label>
<input type="email" name="email" id="email" value="<?=$user['email']?>">
</p>
<p>
<button>保存</button>
</p>
</form>
</body>
</html>
1.3 handle.php
require 'config.php';
// 获取操作
$action = $_GET['action'];
$page = $_GET['p'] ?? null;
$id = $_GET['id'];
switch ($action) {
// 编辑操作: 1: 渲染编辑表单; 2. 执行编辑操作
// 1: 渲染编辑表单
case 'edit':
// 加载,渲染数据编辑表单
include 'edit.php';
break;
// 2. 执行编辑操作
case 'doedit':
// 更新
$sql = 'UPDATE `users` SET `username`=?, `email`=? WHERE `id`=?';
$stmt = $pdo->prepare($sql);
// 新的数据在$_POST
if (!empty($_POST)) {
$stmt->execute([$_POST['username'], $_POST['email'], $id]);
if ($stmt->rowCount() == 1) echo '<script>alert("更新成功");location.href="list.php"</script>';
}
break;
// 删除
case 'delete':
$sql = 'DELETE FROM `users` WHERE `id`=?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
if ($stmt->rowCount() == 1) echo '<script>alert("删除成功");location.href="list.php"</script>';
}
1.4 list.php
<?php require 'config.php' ?>
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据展示</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<table>
<caption>用户信息表</caption>
<thead>
<tr>
<td>id</td>
<td>name</td>
<td>email</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user):?>
<tr>
<!-- 短标签来简化变量的显示 -->
<td><?=$user['id']?></td>
<td><?php echo $user['username'] ?></td>
<td><?=$user['email']?></td>
<td>
<button onclick="location.href='handle.php?action=edit&id=<?=$user['id']?>'">编辑</button>
<button onclick="del(<?=$user['id']?>)">删除</button></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<!-- 显示分页 -->
<p><?php showPage($pages,$page)?></p>
<script>
// 删除
function del(id) {
if(confirm('是否要删除ID为('+ id +')的数据?')){
location.href='handle.php?action=delete&id='+id;
}
}
</script>
</body>
</html>
1.5 style.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
color: #555;
}
body {
display: flex;
flex-direction: column;
align-items: center;
}
/*表格样式*/
table {
width: 80%;
border: 1px solid;
border-collapse: collapse;
text-align: center;
}
table caption {
font-size: 1.2rem;
margin: 10px;
}
table td,
table th {
border: 1px solid;
padding: 5px;
}
table tr:hover {
background-color: #eee;
}
table thead tr:only-of-type {
background-color: lightblue;
}
table button {
width: 56px;
height: 26px;
}
table button:last-of-type {
color: red;
}
table button {
cursor: pointer;
margin: 0 3px;
}
/*分页条样式*/
body > p {
display: flex;
}
p > a {
text-decoration: none;
color: #555;
border: 1px solid;
padding: 5px 10px;
margin: 10px 2px;
}
.active {
background-color: red;
color: white;
border: 1px solid red;
}
小于10页演示:
大于10页演示:
- 编辑演示:
- 编辑演示:
总结
- 把分页样式封装成分页函数,列表页调用;
- 也实现了防PHP中文网分页功能,但方法有很多,我的思路不知道有没有BUG;
- 记录一下朱老师分页讲解原理,感觉讲的特别到位:
分页原理
1. 术语
- 记录索引: 记录在表中的位置,从 0 开始编号(与主键的值无关)
- 偏移量: 每页显示的索引距离起始索引 0 的相对位置
- 显示数量: 每页的显示记录的条数
SELECT * FROM `users` 每页的数量 显示的偏移量
-- 每页的数量: LIMIT n
-- 显示的偏移量: 从哪个索引开始显示 OFFSET m
# 从第1页开始显示5条
SELECT * FROM `users` LIMIT 5 OFFSET 0;
-- (1-1)*5 = 0
# 第二页,从索引5开始显示
SELECT * FROM `users` LIMIT 5 OFFSET 5;
-- (2-1)*5 = 5
# 第3页,从索引10开始,即偏移量为10, 偏移量从第一条记录的索引开始计数
SELECT * FROM `users` LIMIT 5 OFFSET 10;
-- (3-1)*5 = 10
- 分页的时候,一定会提供当前的页数,还有就是每一页的显示的记录数量
- 而偏移量是动态变量的变量,随页数不同而发生变化
2. 计算偏移量
- 偏移量 = (页码 -1) * 每页的显示数量
- offset = (page - 1) * num