PHP手动分页计算怎么写

wen PHP项目 1

本文目录导读:

PHP手动分页计算怎么写

  1. 基础分页计算函数
  2. 在数据库查询中使用
  3. 生成分页导航HTML
  4. 完整示例(PDO使用)
  5. 带搜索条件的分页

在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'] . '">&laquo; 上一页</a></li>';
    } else {
        $html .= '<li class="disabled"><span>&laquo; 上一页</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'] . '">下一页 &raquo;</a></li>';
    } else {
        $html .= '<li class="disabled"><span>下一页 &raquo;</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}"
  1. 总页数 = ceil($total / $perPage),向上取整
  2. 偏移量 = ($currentPage - 1) * $perPage
  3. 当前页码限制:不能小于1,不能大于总页数
  4. SQL使用LIMIT offset, perPage
  5. 页码范围控制:当页数很多时,只显示部分页码(如前后各2个),避免输出太多按钮

这个实现方式不依赖任何框架,可以用于纯PHP项目,也可以很容易地适配到ThinkPHP、Laravel等框架中。

抱歉,评论功能暂时关闭!