本文目录导读:

在PHP中手动实现分页计算,需要处理几个关键参数:当前页码、每页显示数量、总记录数,然后计算总页数和偏移量。
以下是完整的实现方案:
基础分页计算函数
<?php
/**
* 计算分页参数
* @param int $total 总记录数
* @param int $perPage 每页显示数量(默认10)
* @param int $currentPage 当前页码(默认1)
* @return array 分页相关的所有参数
*/
function paginate($total, $perPage = 10, $currentPage = 1) {
// 1. 计算总页数(向上取整)
$totalPages = ceil($total / $perPage);
// 2. 确保总页数至少为1
$totalPages = max(1, $totalPages);
// 3. 当前页码安全检查
// 不能小于1,不能大于总页数
$currentPage = max(1, min($currentPage, $totalPages));
// 4. 计算偏移量(LIMIT子句的第一个参数)
$offset = ($currentPage - 1) * $perPage;
// 5. 返回所有计算好的参数
return [
'total' => $total, // 总记录数
'perPage' => $perPage, // 每页数量
'currentPage' => $currentPage, // 当前页码
'totalPages' => $totalPages, // 总页数
'offset' => $offset, // 用于SQL的OFFSET
'hasPrevious' => $currentPage > 1, // 是否有上一页
'hasNext' => $currentPage < $totalPages, // 是否有下一页
'previousPage' => $currentPage - 1, // 上一页页码
'nextPage' => $currentPage + 1, // 下一页页码
'startRecord' => $offset + 1, // 当前页开始的记录数(用于显示)
'endRecord' => min($offset + $perPage, $total) // 当前页结束的记录数
];
}
在数据库查询中使用
<?php
// 示例:查询用户列表并分页
// 1. 从GET获取当前页码,默认第一页
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 15; // 每页15条记录
// 2. 获取总记录数
$countSql = "SELECT COUNT(*) as total FROM users";
$countResult = $pdo->query($countSql);
$total = $countResult->fetch(PDO::FETCH_ASSOC)['total'];
// 3. 计算分页参数
$pagination = paginate($total, $perPage, $page);
// 4. 查询当前页的数据
$sql = "SELECT * FROM users ORDER BY id DESC LIMIT {$pagination['offset']}, {$perPage}";
$stmt = $pdo->query($sql);
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 5. 输出数据
foreach ($users as $user) {
echo "用户名: " . htmlspecialchars($user['username']) . "<br>";
}
// 6. 输出分页导航
echo renderPagination($pagination);
?>
生成分页导航HTML
<?php
/**
* 生成分页导航HTML
* @param array $pagination paginate()函数的返回值
* @return string 分页HTML
*/
function renderPagination($pagination) {
// 如果只有一页,不需要显示分页
if ($pagination['totalPages'] <= 1) {
return '';
}
$html = '<nav class="pagination">';
$html .= '<ul>';
// 上一页按钮
if ($pagination['hasPrevious']) {
$html .= '<li><a href="?page=' . $pagination['previousPage'] . '">« 上一页</a></li>';
} else {
$html .= '<li class="disabled"><span>« 上一页</span></li>';
}
// 页码数字(显示带限制的页码范围)
$start = max(1, $pagination['currentPage'] - 2); // 当前页前2页
$end = min($pagination['totalPages'], $pagination['currentPage'] + 2); // 当前页后2页
for ($i = $start; $i <= $end; $i++) {
if ($i == $pagination['currentPage']) {
$html .= '<li class="active"><span>' . $i . '</span></li>';
} else {
$html .= '<li><a href="?page=' . $i . '">' . $i . '</a></li>';
}
}
// 下一页按钮
if ($pagination['hasNext']) {
$html .= '<li><a href="?page=' . $pagination['nextPage'] . '">下一页 »</a></li>';
} else {
$html .= '<li class="disabled"><span>下一页 »</span></li>';
}
$html .= '</ul>';
// 显示记录信息
$html .= '<div class="page-info">';
$html .= '共 ' . $pagination['total'] . ' 条,';
$html .= '第 ' . $pagination['startRecord'] . '-' . $pagination['endRecord'] . ' 条,';
$html .= '当前第 ' . $pagination['currentPage'] . '/' . $pagination['totalPages'] . ' 页';
$html .= '</div>';
$html .= '</nav>';
return $html;
}
?>
完整示例(PDO使用)
<?php
// 完整的分页实现示例
// 数据库连接
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8mb4';
$pdo = new PDO($dsn, 'username', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 分页参数
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 10;
try {
// 查询总数
$stmt = $pdo->query("SELECT COUNT(*) FROM articles");
$total = $stmt->fetchColumn();
// 计算分页
$pagination = paginate($total, $perPage, $page);
// 查询数据
$sql = "SELECT * FROM articles ORDER BY created_at DESC
LIMIT {$pagination['offset']}, {$pagination['perPage']}";
$stmt = $pdo->query($sql);
$articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 显示数据
foreach ($articles as $article) {
echo "<h2>{$article['title']}</h2>";
echo "<p>" . mb_substr($article['content'], 0, 100) . "...</p>";
echo "<hr>";
}
// 显示分页
echo renderPagination($pagination);
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
带搜索条件的分页
<?php
/**
* 带搜索条件的分页示例
*/
$search = isset($_GET['search']) ? trim($_GET['search']) : '';
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 10;
// 构建条件
$where = '';
$params = [];
if ($search !== '') {
$where = "WHERE title LIKE ? OR content LIKE ?";
$params = ["%$search%", "%$search%"];
}
// 查询总数
$stmt = $pdo->prepare("SELECT COUNT(*) FROM articles $where");
$stmt->execute($params);
$total = $stmt->fetchColumn();
// 计算分页
$pagination = paginate($total, $perPage, $page);
// 查询数据
$sql = "SELECT * FROM articles $where
ORDER BY created_at DESC
LIMIT {$pagination['offset']}, {$pagination['perPage']}";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 分页链接需要保留搜索参数
$queryString = http_build_query(['search' => $search]);
// HTML中的分页链接改为: "?page={$i}&{$queryString}"
- 总页数 =
ceil($total / $perPage),向上取整 - 偏移量 =
($currentPage - 1) * $perPage - 当前页码限制:不能小于1,不能大于总页数
- SQL使用:
LIMIT offset, perPage - 页码范围控制:当页数很多时,只显示部分页码(如前后各2个),避免输出太多按钮
这个实现方式不依赖任何框架,可以用于纯PHP项目,也可以很容易地适配到ThinkPHP、Laravel等框架中。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播