🤖 AI智能摘要
暂未配置
前言
实际项目当中数据库数据会有成百上千条,不可能一次性全部展示在页面上,这时就要使用分页技术。分页几乎是每一个网站必备功能,文章列表、后台管理、留言列表都会用到。本章讲解分页计算原理、MySQL 的 limit 分页语法,最后做一个完整综合实战项目:新闻留言管理系统,把前面学过的 SQL 预处理、Session 登录、文件上传全部整合。
一、MySQL LIMIT 分页语法
LIMIT 偏移量,每页条数
- 偏移量:从第几条开始读取,第一条数据偏移量是 0
- 每页条数:一页显示多少条数据
示例:
# 第1页,读取5条,从0开始
SELECT * FROM news ORDER BY id DESC LIMIT 0,5;
#第2页,读取5条,从5开始
SELECT * FROM news ORDER BY id DESC LIMIT 5,5;
#第3页,读取5条,从10开始
SELECT * FROM news ORDER BY id DESC LIMIT 10,5;二、分页相关计算公式
- 当前页码:
$page,URL 参数获取?page=1 - 每页显示条数:
$pageSize = 5 - 偏移量:
$offset = ($page‑1)*$pageSize - 数据总条数:使用
COUNT(*)统计数据库记录总数 - 总页数:
$totalPage = ceil($totalCount / $pageSize)
ceil () 函数:向上取整,有余数就多算一页
三、PHP 分页完整代码示例
准备数据表 news
CREATE TABLE `news`(
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(100) NOT NULL,
content TEXT,
addtime DATETIME
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;list.php
<?php
$conn = mysqli_connect("127.0.0.1","root","root","php_demo");
mysqli_set_charset($conn,"utf8mb4");
//1 获取当前页码
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$pageSize = 5; //一页5条
//2 计算偏移量
$offset = ($page - 1) * $pageSize;
//3 查询总数据条数
$countSql = "SELECT COUNT(*) FROM news";
$countRes = mysqli_query($conn,$countSql);
$totalCount = mysqli_fetch_array($countRes)[0];
//4 计算总页数
$totalPage = ceil($totalCount / $pageSize);
//页码边界处理,防止page=0或者page超过总页数
if($page < 1) $page =1;
if($page > $totalPage && $totalPage>0) $page = $totalPage;
//5 读取当前页数据
$sql = "SELECT * FROM news ORDER BY id DESC LIMIT {$offset},{$pageSize}";
$result = mysqli_query($conn,$sql);
$list = mysqli_fetch_all($result,MYSQLI_ASSOC);
?>
<h2>新闻列表</h2>
<?php foreach($list as $v): ?>
<div>
<h3><?php echo $v['title'] ?></h3>
<p><?php echo $v['content'] ?></p>
<span><?php echo $v['addtime'] ?></span>
<hr>
</div>
<?php endforeach; ?>
<!--分页按钮-->
<div class="page">
<?php if($page>1):?>
<a href="list.php?page=<?php echo $page‑1 ?>">上一页</a>
<?php endif;?>
<span>第 <?php echo $page; ?> / <?php echo $totalPage; ?> 页</span>
<?php if($page < $totalPage):?>
<a href="list.php?page=<?php echo $page+1 ?>">下一页</a>
<?php endif;?>
</div>
<?php mysqli_close($conn); ?>四、分页常见 bug
- URL 参数 page 传入负数、字符,必须用
intval()转为数字; - 总数据等于 0 的时候,总页数为 0,需要做判断,避免出现 0 页;
- LIMIT 后面两个参数全部必须是数字,不要直接接收用户 get 参数,一定要 intval 处理;
- 翻页越界:page 大于总页数,强制赋值为最大页码。
五、综合实战:简易新闻后台管理系统
项目包含全部知识点:Session 登录、预处理防注入、分页、文件上传、增删改查。
一共 7 个文件:
- admin\_login.html 后台登录表单
- admin\_login.php 登录处理
- admin\_index.php 后台首页(需要登录)
- news\_list.php 新闻列表 + 分页
- news\_add.php 新增新闻(含图片上传)
- news\_edit.php 修改新闻
- news\_del.php 删除新闻
1. admin\_login.html
<form action="admin_login.php" method="post">
<h3>后台管理登录</h3>
账号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录后台">
</form>2. admin\_login.php
<?php
session_start();
$username = trim($_POST['username']);
$password = trim($_POST['password']);
if(empty($username) || empty($password)){
echo "账号密码不能为空 <a href='admin_login.html'>返回</a>";
exit;
}
$conn = mysqli_connect("127.0.0.1","root","root","php_demo");
mysqli_set_charset($conn,"utf8mb4");
$sql = "SELECT id FROM user WHERE username=? AND password=?";
$stmt = mysqli_prepare($conn,$sql);
mysqli_stmt_bind_param($stmt,"ss",$username,$password);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt,$uid);
mysqli_stmt_fetch($stmt);
if(!empty($uid)){
$_SESSION['admin_login'] = true;
header("Location:admin_index.php");
exit;
}else{
echo "账号密码错误 <a href='admin_login.html'>返回</a>";
}
mysqli_stmt_close($stmt);
mysqli_close($conn);
?>3.admin\_index.php(登录校验)
<?php
session_start();
if(!isset($_SESSION['admin_login']) || $_SESSION['admin_login']!==true){
header("Location:admin_login.html");
exit;
}
?>
<h1>网站后台管理中心</h1>
<ul>
<li><a href="news_list.php">新闻管理(分页列表)</a></li>
<li><a href="news_add.php">添加新闻</a></li>
<li><a href="logout.php">退出登录</a></li>
</ul>4.news\_list.php 新闻分页列表
<?php
session_start();
if(!isset($_SESSION['admin_login'])){
header("Location:admin_login.html");
exit;
}
$conn = mysqli_connect("127.0.0.1","root","root","php_demo");
mysqli_set_charset($conn,"utf8mb4");
$page = isset($_GET['page'])?intval($_GET['page']):1;
$pageSize = 6;
$offset = ($page‑1)*$pageSize;
//统计总数
$countSql = "SELECT COUNT(id) FROM news";
$cr = mysqli_query($conn,$countSql);
$total = mysqli_fetch_array($cr)[0];
$totalPage = ceil($total/$pageSize);
if($page<1)$page=1;
if($page>$totalPage && $totalPage>0)$page=$totalPage;
$sql = "SELECT * FROM news ORDER BY id DESC LIMIT {$offset},{$pageSize}";
$res = mysqli_query($conn,$sql);
$data = mysqli_fetch_all($res,MYSQLI_ASSOC);
?>
<h2>新闻列表</h2>
<a href="news_add.php">➕添加新闻</a>
<table border="1" cellpadding="6">
<tr>
<th>ID</th>
<th>标题</th>
<th>时间</th>
<th>操作</th>
</tr>
<?php foreach($data as $v):?>
<tr>
<td><?php echo $v['id'] ?></td>
<td><?php echo $v['title'] ?></td>
<td><?php echo $v['addtime'] ?></td>
<td>
<a href="news_edit.php?id=<?php echo $v['id'] ?>">编辑</a>
<a href="news_del.php?id=<?php echo $v['id'] ?>" onclick="return confirm('确认删除?')">删除</a>
</td>
</tr>
<?php endforeach;?>
</table>
<div>
<?php if($page>1):?>
<a href="news_list.php?page=<?php echo $page‑1 ?>">上一页</a>
<?php endif;?>
第<?php echo $page ?>页 / 共<?php echo $totalPage ?>页
<?php if($page<$totalPage):?>
<a href="news_list.php?page=<?php echo $page+1 ?>">下一页</a>
<?php endif;?>
</div>
<?php mysqli_close($conn); ?>\#\#\#5.news\_add.php 添加新闻(图片上传)
<?php
session_start();
if(!isset($_SESSION['admin_login'])){
header("Location:admin_login.html");
exit;
}
$conn = mysqli_connect("127.0.0.1","root","root","php_demo");
mysqli_set_charset($conn,"utf8mb4");
$title = "";
$content = "";
$imgUrl = "";
if($_SERVER['REQUEST_METHOD'] === "POST"){
$title = trim($_POST['title']);
$content = trim($_POST['content']);
//图片上传处理
if($_FILES['img']['error'] === 0){
$ext = strtolower(pathinfo($_FILES['img']['name'],PATHINFO_EXTENSION));
$allow = ['jpg','png','gif','jpeg'];
if(in_array($ext,$allow)){
if(!file_exists("./upload")) mkdir("./upload",0777,true);
$newName = time().rand(1000,9999).".".$ext;
$save = "./upload/".$newName;
move_uploaded_file($_FILES['img']['tmp_name'],$save);
$imgUrl = $save;
}
}
//预处理插入数据库
$now = date("Y‑m‑d H:i:s");
$sql = "INSERT INTO news(title,content,img,addtime) VALUES (?,?,?,?)";
$stmt = mysqli_prepare($conn,$sql);
mysqli_stmt_bind_param($stmt,"ssss",$title,$content,$imgUrl,$now);
if(mysqli_stmt_execute($stmt)){
echo "新增成功!<a href='news_list.php'>返回列表</a>";
exit;
}else{
echo "新增失败";
}
}
?>
<form method="post" action="" enctype="multipart/form‑data">
标题:<input type="text" name="title"><br>
图片:<input type="file" name="img"><br>
内容:<textarea name="content" rows="8" cols="60"></textarea><br>
<input type="submit" value="提交新闻">
</form>\#\#\#6.news\_edit.php 修改新闻
<?php
session_start();
if(!isset($_SESSION['admin_login'])){
header("Location:admin_login.html");
exit;
}
$id = intval($_GET['id']);
$conn = mysqli_connect("127.0.0.1","root","root","php_demo");
mysqli_set_charset($conn,"utf8mb4");
//读取原有数据
$sql = "SELECT title,content,img FROM news WHERE id=?";
$stmt = mysqli_prepare($conn,$sql);
mysqli_stmt_bind_param($stmt,"i",$id);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt,$title,$content,$oldImg);
mysqli_stmt_fetch($stmt);
//提交修改
if($_SERVER['REQUEST_METHOD']=="POST"){
$title = trim($_POST['title']);
$content = trim($_POST['content']);
$newImg = $oldImg;
//上传新图片
if($_FILES['img']['error']==0){
$ext = strtolower(pathinfo($_FILES['img']['name'],PATHINFO_EXTENSION));
$allow = ['jpg','png','gif','jpeg'];
if(in_array($ext,$allow)){
$name = time().rand(1000,9999).".".$ext;
$path = "./upload/".$name;
move_uploaded_file($_FILES['img']['tmp_name'],$path);
$newImg = $path;
}
}
$updateSql = "UPDATE news SET title=?,content=?,img=? WHERE id=?";
$st = mysqli_prepare($conn,$updateSql);
mysqli_stmt_bind_param($st,"sssi",$title,$content,$newImg,$id);
if(mysqli_stmt_execute($st)){
echo "修改完成 <a href='news_list.php'>返回列表</a>";
exit;
}
}
?>
<form method="post" enctype="multipart/form‑data">
标题:<input type="text" name="title" value="<?php echo htmlspecialchars($title) ?>"><br>
原图:<?php if(!empty($oldImg)) echo "<img src='$oldImg' width='120'>"; ?><br>
更换图片:<input type="file" name="img"><br>
内容:<textarea name="content" rows="8"><?php echo htmlspecialchars($content) ?></textarea><br>
<input type="submit" value="保存修改">
</form>\#\#\#7.news\_del.php 删除新闻
<?php
session_start();
if(!isset($_SESSION['admin_login'])){
header("Location:admin_login.html");
exit;
}
$id = intval($_GET['id']);
$conn = mysqli_connect("127.0.0.1","root","root","php_demo");
mysqli_set_charset($conn,"utf8mb4");
$sql = "DELETE FROM news WHERE id=?";
$stmt = mysqli_prepare($conn,$sql);
mysqli_stmt_bind_param($stmt,"i",$id);
mysqli_stmt_execute($stmt);
header("Location:news_list.php");
exit;
?>\#\#\#8.logout.php 退出登录
<?php
session_start();
$_SESSION = [];
session_destroy();
header("Location:admin_login.html");
exit;
?>六、本章总结
- MySQL 分页依靠
LIMIT 偏移量,条数实现,偏移量 =(当前页‑1)* 每页条数; ceil()向上取整,用来计算总页数;- GET 接收页码,必须使用
intval()强制转为数字,防止注入; - 一定要做页码边界判断,防止页码越界;
- 综合项目整合:Session 登录验证、mysqli 预处理防注入、文件上传、增删改查、分页;
- 后台所有页面开头必须做登录校验,没有登录直接跳转到登录页面;
- 输出到 HTML 页面的数据,建议使用
htmlspecialchars()转义,防止 XSS 跨站脚本攻击。
第十一章结束,PHP 基础到此全部完成。后面就可以学习 ThinkPHP 框架开发。
如果你需要,我可以把第十一章整理为纯文档格式给你复制保存。
(注:部分内容可能由 AI 生成)