分頁是 Web 應用中最常見的需求之一。本文提供一個結構清晰、易於擴充的 Page 類別,支援首頁、尾頁、上一頁、下一頁、頁碼列表與下拉跳轉等多種導航模式,並可自訂顯示文字與每頁筆數。
<?php
/************************************************************************************
* 完美分頁類 - 支援自訂分頁樣式與多種導航模式
************************************************************************************
* @author 北海情書 (hackmyth@163.com)
* @date 2011-07-18
************************************************************************************/
class Page {
private $total; // 資料總筆數
private $listRows; // 每頁顯示筆數
private $limit; // SQL LIMIT 子句
private $pageNum; // 總頁數
private $page; // 當前頁碼
private $config = array(
'head' => "條記錄",
'prev' => "上一頁",
'next' => "下一頁",
'first' => "首頁",
'last' => "末頁"
);
/**
* 建構子
* @param int $total 總記錄數
* @param int $listRows 每頁筆數,預設 10
*/
public function __construct($total, $listRows = 10) {
$this->total = $total;
$this->listRows = $listRows;
$this->pageNum = ceil($this->total / $this->listRows); // 計算總頁數
// 防止頁碼越界
if (isset($_GET['page']) && $_GET['page'] > $this->pageNum) {
$_GET['page'] = $this->pageNum;
}
$this->page = !empty($_GET['page']) ? (int)$_GET['page'] : 1;
$this->limit = $this->setPage();
}
// 魔術方法:只允許讀取 limit 屬性
public function __get($args) {
if ($args === 'limit') {
return $this->limit;
}
return null;
}
// 計算 LIMIT 子句
private function setPage() {
return "LIMIT " . ($this->page - 1) * $this->listRows . ", " . $this->listRows;
}
// 導航連結產生方法
private function prev() { return $this->page > 1 ? "<a href='?page=" . ($this->page - 1) . "'>" . $this->config['prev'] . "</a>" : ""; }
private function next() { return $this->page < $this->pageNum ? "<a href='?page=" . ($this->page + 1) . "'>" . $this->config['next'] . "</a>" : ""; }
private function first() { return $this->page > 1 ? "<a href='?page=1'>" . $this->config['first'] . "</a>" : ""; }
private function last() { return $this->page < $this->pageNum ? "<a href='?page=" . $this->pageNum . "'>" . $this->config['last'] . "</a>" : ""; }
// 頁碼列表
private function pagelist() {
$lists = '';
for ($i = 1; $i <= $this->pageNum; $i++) {
$lists .= ($i == $this->page) ? "<span class='current'>$i</span> " : "<a href='?page=$i'>$i</a> ";
}
return $lists;
}
/**
* 產生分頁導航 HTML
* @param array $display 要顯示的元素索引:1=統計資訊, 2=上一頁, 3=下一頁, 4=首頁, 5=尾頁, 6=頁碼列表
* @return string
*/
public function fpage($display = array(1, 2, 3, 4, 5, 6)) {
$html = array(
1 => "共有 {$this->total}{$this->config['head']}",
2 => $this->prev(),
3 => $this->next(),
4 => $this->first(),
5 => $this->last(),
6 => $this->pagelist()
);
$fpage = '';
foreach ($display as $index) {
if (isset($html[$index])) $fpage .= $html[$index] . " ";
}
return $fpage;
}
}
?>
<?php
require_once 'Page.php';
// 假設從資料庫取得總筆數
$total = 125; // 實際應用中替換為 SELECT COUNT(*) 查詢結果
// 實例化分頁類(每頁 10 筆)
$page = new Page($total, 10);
// 取得 LIMIT 子句用於 SQL 查詢
$sql = "SELECT * FROM articles {$page->limit}";
$result = mysql_query($sql); // 實際請使用 PDO 或 MySQLi
// 輸出分頁導航(顯示所有元素)
echo $page->fpage();
// 或自訂顯示:僅顯示統計、首頁、上一頁、下一頁、尾頁、頁碼列表
// echo $page->fpage(array(1, 4, 2, 3, 5, 6));
?>
/page/3)或自訂查詢參數名稱。ajax() 方法回傳 JSON 格式分頁資料,配合前端無刷新載入。COUNT(*) 結果快取以減少資料庫負載。