分頁需要兩個關鍵參數:
$pageSize:每頁筆數(如 10、20、50)$currentPage:當前頁碼(從 1 開始)資料庫查詢使用 LIMIT offset, row_count:
offset = ($currentPage - 1) * $pageSize
row_count = $pageSize
SELECT * FROM table LIMIT offset, row_count
<?php
// config.php
$dsn = 'mysql:host=localhost;dbname=shop;charset=utf8mb4';
$user = 'root';
$pass = '';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $user, $pass, $options);
// list.php
$pageSize = 10;
$currentPage = max(1, (int)($_GET['page'] ?? 1));
// 1. 取得總筆數
$totalStmt = $pdo->query("SELECT COUNT(*) FROM products");
$totalRows = $totalStmt->fetchColumn();
$totalPages = (int)ceil($totalRows / $pageSize);
// 修正頁碼範圍
if ($currentPage > $totalPages) $currentPage = max(1, $totalPages);
$offset = ($currentPage - 1) * $pageSize;
// 2. 查詢當頁資料
$dataStmt = $pdo->prepare("SELECT id, name, price, created_at FROM products ORDER BY created_at DESC LIMIT :limit OFFSET :offset");
$dataStmt->bindValue(':limit', $pageSize, PDO::PARAM_INT);
$dataStmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$dataStmt->execute();
$products = $dataStmt->fetchAll();
// 3. 顯示資料
?>
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>商品列表</title></head><body>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>ID</th><th>名稱</th><th>價格</th><th>建立時間</th></tr>
<?php foreach ($products as $p): ?>
<tr>
<td><?= $p['id'] ?></td>
<td><?= htmlspecialchars($p['name']) ?></td>
<td>$<?= number_format($p['price'], 2) ?></td>
<td><?= $p['created_at'] ?></td>
</tr>
<?php endforeach; ?>
</table>
<nav aria-label="分頁導航">
<?php if ($totalPages > 1): ?>
<ul style="display:flex; gap:0.5rem; list-style:none; padding:0;">
<?php if ($currentPage > 1): ?>
<li><a href="?page=<?= $currentPage - 1 ?>">上一頁</a></li>
<?php endif; ?>
<?php
// 顯示頁碼範圍:當前頁前後各 2 頁
$start = max(1, $currentPage - 2);
$end = min($totalPages, $currentPage + 2);
if ($start > 1) echo '<li><a href="?page=1">1</a></li><li>...</li>';
for ($i = $start; $i <= $end; $i++): ?>
<li><a href="?page=<?= $i ?>" style="<?= $i === $currentPage ? 'font-weight:bold;color:red;' : '' ?>"><?= $i ?></a></li>
<?php endfor; ?>
<?php if ($end < $totalPages) echo '<li>...</li><li><a href="?page=<?= $totalPages ?>"><?= $totalPages ?></a></li>'; ?>
<?php if ($currentPage < $totalPages): ?>
<li><a href="?page=<?= $currentPage + 1 ?>">下一頁</a></li>
<?php endif; ?>
</ul>
<p>共 <?= $totalRows ?> 筆 / 第 <?= $currentPage ?> / <?= $totalPages ?> 頁</p>
<?php endif; ?>
</nav>
</body></html>
| 問題 | 解決方案 |
|---|---|
| OFFSET 深分頁效能差 | 游標分頁:WHERE id > :last_id ORDER BY id LIMIT 10(需唯一遞增鍵) |
| COUNT(*) 全表掃描慢 | 近似值:EXPLAIN SELECT COUNT(*)、資訊表 TABLE_ROWS、快取總數、觸發器維護計數表 |
| 頻繁重複查詢 | Redis 快取熱門頁面、查詢結果快取 |