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

PHP MySQL 分頁顯示核心原理與現代實作指南

     編輯:PHP 綜合知識

分頁核心邏輯

分頁需要兩個關鍵參數:

  • $pageSize:每頁筆數(如 10、20、50)
  • $currentPage:當前頁碼(從 1 開始)

資料庫查詢使用 LIMIT offset, row_count:

offset = ($currentPage - 1) * $pageSize
row_count = $pageSize

SELECT * FROM table LIMIT offset, row_count

完整 PDO 實作範例

<?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>

大資料量效能優化

游標分頁實作(適合無限滾動/大數據)

<?php
$pageSize = 20;
$lastId = (int)($_GET['last_id'] ?? 0);  // 第一頁傳 0

$stmt = $pdo->prepare("SELECT id, name, price FROM products WHERE id > :last_id ORDER BY id ASC LIMIT :limit");
$stmt->bindValue(':last_id', $lastId, PDO::PARAM_INT);
$stmt->bindValue(':limit', $pageSize, PDO::PARAM_INT);
$stmt->execute();
$items = $stmt->fetchAll();

$nextLastId = $items ? end($items)['id'] : 0;
$hasMore = count($items) === $pageSize;

// JSON 回應(AJAX 無限滾動)
header('Content-Type: application/json');
echo json_encode([
    'items' => $items,
    'next_last_id' => $nextLastId,
    'has_more' => $hasMore,
]);

建立測試資料表

CREATE TABLE `products` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `name` VARCHAR(200) NOT NULL,
    `price` DECIMAL(10,2) NOT NULL DEFAULT 0,
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 插入測試資料
INSERT INTO `products` (`name`, `price`) VALUES
('商品 A', 100.00), ('商品 B', 250.50), ('商品 C', 89.90);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題解決方案
OFFSET 深分頁效能差游標分頁:WHERE id > :last_id ORDER BY id LIMIT 10(需唯一遞增鍵)
COUNT(*) 全表掃描慢近似值:EXPLAIN SELECT COUNT(*)、資訊表 TABLE_ROWS、快取總數、觸發器維護計數表
頻繁重複查詢Redis 快取熱門頁面、查詢結果快取