首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 實現數據分頁顯示:從基礎邏輯到大數據優化的完整方案

     編輯:PHP 相關知識

PHP 實現數據分頁顯示:從基礎邏輯到大數據優化的完整方案

分頁是後台管理、列表頁的核心功能。本文從基礎分頁邏輯到大數據場景優化、現代框架集成,提供生產級分頁實現方案。

核心分頁參數

  • $pageSize:每頁條數(如 10、20、50)
  • $pageNow:當前頁碼(從 1 開始)
  • $rowCount:總記錄數(需 SELECT COUNT(*) 獲取)
  • $pageCount:總頁數 = ceil($rowCount / $pageSize)

方案一:基礎分頁(適合中小數據量)

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$pageSize = 10;
$pageNow  = max(1, (int)($_GET['page'] ?? 1));

// 1. 獲取總記錄數
$stmt = $pdo->query("SELECT COUNT(*) FROM users");
$rowCount = $stmt->fetchColumn();
$pageCount = (int)ceil($rowCount / $pageSize);

// 2. 修正頁碼邊界
$pageNow = min($pageNow, max(1, $pageCount));

// 3. 計算偏移量並查詢數據
$offset = ($pageNow - 1) * $pageSize;
$stmt = $pdo->prepare("SELECT * FROM users ORDER BY id DESC LIMIT :offset, :size");
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->bindValue(':size', $pageSize, PDO::PARAM_INT);
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>

<!-- 顯示數據 -->
<table>
    <thead><tr><th>ID</th><th>用戶名</th><th>郵箱</th></tr></thead>
    <tbody>
    <?php foreach ($users as $u): ?>
        <tr><td><?= $u['id'] ?></td><td><?= htmlspecialchars($u['username']) ?></td><td><?= $u['email'] ?></td></tr>
    <?php endforeach; ?>
    </tbody>
</table>

<!-- 分頁導航 -->
<div class="pagination">
    <?php if ($pageNow > 1): ?>
        <a href="?page=1">首頁</a>
        <a href="?page=<?= $pageNow - 1 ?>">上一頁</a>
    <?php endif; ?>

    <?php
    // 顯示頁碼範圍:當前頁前後各 2 頁
    $start = max(1, $pageNow - 2);
    $end   = min($pageCount, $pageNow + 2);
    for ($i = $start; $i <= $end; $i++): ?>
        <a href="?page=<?= $i ?>" class="<?= $i == $pageNow ? 'active' : '' ?>"><?= $i ?></a>
    <?php endfor; ?>

    <?php if ($pageNow < $pageCount): ?>
        <a href="?page=<?= $pageNow + 1 ?>">下一頁</a>
        <a href="?page=<?= $pageCount ?>">尾頁</a>
    <?php endif; ?>
    
    <span class="info">第 <?= $pageNow ?> / <?= $pageCount ?> 頁,共 <?= $rowCount ?> 條</span>
</div>

方案二:大數據量優化(百萬級以上)

問題:LIMIT offset, size 在大偏移量時性能極差(MySQL 需掃描前 offset 行)。

優化 1:游標分頁 / Keyset Pagination(推薦)

<?php
// 利用唯一遞增字段(如 id、created_at+id)作為游標
$pageSize = 20;
$cursor   = (int)($_GET['cursor'] ?? 0); // 上一頁最後一條的 id
$direction = $_GET['dir'] ?? 'next';     // 'next' 或 'prev'

if ($direction === 'next') {
    $stmt = $pdo->prepare("SELECT * FROM users WHERE id > :cursor ORDER BY id ASC LIMIT :size");
    $stmt->bindValue(':cursor', $cursor, PDO::PARAM_INT);
} else {
    $stmt = $pdo->prepare("SELECT * FROM users WHERE id < :cursor ORDER BY id DESC LIMIT :size");
    $stmt->bindValue(':cursor', $cursor, PDO::PARAM_INT);
}
$stmt->bindValue(':size', $pageSize, PDO::PARAM_INT);
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 前端只需傳遞 last_id 作為下一頁 cursor
// 缺點:無法跳轉到任意頁,僅支持「上一頁/下一頁」或無限滾動
?>

優化 2:延遲關聯

-- 先只查主鍵 ID,再回表查詳情
SELECT u.* FROM users u
JOIN (SELECT id FROM users ORDER BY id DESC LIMIT 100000, 20) tmp USING (id)
ORDER BY u.id DESC;

優化 3:緩存總數 + 預計算頁碼

$rowCount = $redis->get('users:total_count');
if ($rowCount === false) {
    $rowCount = $pdo->query("SELECT COUNT(*) FROM users")->fetchColumn();
    $redis->setex('users:total_count', 300, $rowCount); // 緩存 5 分鐘
}

現代框架集成示例(Laravel / ThinkPHP / Yii2)

// Laravel
$users = User::orderBy('id', 'desc')->paginate(15);
return view('users.index', compact('users'));

// Blade 模板
{{ $users->links() }} // 自動生成完整分頁導航

// ThinkPHP 6+
$list = Db::name('users')->order('id desc')->paginate(15);
$this->assign('list', $list);
// 模板:{$list->render()}

// Yii2
use yii\data\Pagination;
$query = User::find()->orderBy(['id' => SORT_DESC]);
$pages = new Pagination(['totalCount' => $query->count(), 'pageSize' => 15]);
$models = $query->offset($pages->offset)->limit($pages->limit)->all();
// 視圖:echo LinkPager::widget(['pagination' => $pages]);

前端分頁組件最佳實踐

  • 使用語義化 HTML:<nav aria-label="分頁導航"><ul class="pagination">...
  • 當前頁 aria-current="page",禁用狀態 aria-disabled="true"
  • 提供「每頁顯示條數」選擇器(10/20/50/100)
  • 大數據場景採用「無限滾動」或「加載更多」替代傳統頁碼
  • URL 保持可分享:分頁狀態通過 Query String 傳遞,支持瀏覽器前進/後退

選型指南:數據量 < 10 萬 → 直接 LIMIT offset, size;10 萬 - 100 萬 → 延遲關聯或緩存總數;> 100 萬 → **強制使用游標分頁**,放棄任意頁跳轉,改用無限滾動/載入更多交互模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved