分頁是處理大量資料的標準做法,將資料庫結果集切割成固定大小的區塊逐頁呈現。核心只需兩個參數:
$pageSize)$currentPage)MySQL 使用 LIMIT offset, rows 語法:
-- 第 1 頁(每頁 10 筆) SELECT * FROM table LIMIT 0, 10; -- 第 2 頁 SELECT * FROM table LIMIT 10, 10; -- 第 N 頁通用公式 SELECT * FROM table LIMIT (N-1)*pageSize, pageSize;
<?php
// 取得當前頁碼
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$pageSize = 10;
// 計算總筆數與總頁數
$total = (int)mysqli_query($link, "SELECT COUNT(*) FROM articles")->fetch_row()[0];
$totalPages = $total ? ceil($total / $pageSize) : 0;
// 取得當頁資料
$offset = ($page - 1) * $pageSize;
$data = mysqli_query($link, "SELECT * FROM articles ORDER BY id DESC LIMIT $offset, $pageSize")
->fetch_all(MYSQLI_ASSOC);
// 產生分頁連結
$links = '';
if ($page > 1) $links .= '<a href="?page=1">首頁</a> | <a href="?page='.($page-1).'">上一頁</a> | ';
for ($i = max(1, $page-2); $i <= min($totalPages, $page+2); $i++) {
$links .= $i == $page ? " [$i] " : ' <a href="?page='.$i.'">'.$i.'</a> ';
}
if ($page < $totalPages) $links .= '| <a href="?page='.($page+1).'">下一頁</a> | <a href="?page='.$totalPages.'">尾頁</a>';
?>
採用 PEAR::DB 確保資料庫相容性,分離資料邏輯與顯示邏輯:
class Pager {
public $pageSize, $currentPage, $numPages, $numItems;
public $isFirstPage, $isLastPage;
private $sql, $db;
public function __construct($options) {
global $db; $this->db = $db;
foreach ($options as $k => $v) if (property_exists($this, $k)) $this->$k = $v;
$this->calculate();
}
private function calculate() {
if (!$this->numItems) {
$this->numItems = $this->db->query($this->sql)->numRows();
}
$this->numPages = $this->numItems ? ceil($this->numItems / $this->pageSize) : 0;
$this->isFirstPage = $this->currentPage == 1;
$this->isLastPage = $this->currentPage == $this->numPages;
}
public function getPageData() {
if (!$this->numItems) return [];
$from = ($this->currentPage - 1) * $this->pageSize;
return $this->db->limitQuery($this->sql, $from, $this->pageSize)->fetchAll();
}
}
class MemberPager extends Pager {
public function render() {
$data = $this->getPageData();
echo '<table>';
foreach ($data as $row) {
echo "<tr><td>{$row['username']}</td><td>{$row['email']}</td></tr>";
}
echo '</table>';
$this->renderNav();
}
}
| 資料庫 | 分頁語法 |
|---|---|
| MySQL | LIMIT offset, rows |
| PostgreSQL | LIMIT rows OFFSET offset |
| SQL Server | OFFSET offset ROWS FETCH NEXT rows ROWS ONLY |
| Oracle | ROW_NUMBER() OVER () 分頁查詢 |
使用 PEAR::DB::limitQuery() 可自動處理差異。
$_GET['page'] 為正整數