class Pagination {
var $pageSize; // 每頁筆數
var $pageNo; // 當前頁碼
var $rowCount; // 總筆數
var $pageCount; // 總頁數
var $records = array(); // 當前頁資料物件陣列
var $currentPageSize; // 當前頁實際筆數
var $currentPageStartNo; // 當前頁起始序號
// 導航輔助方法
function hasNextPage() { return $this->pageNo < $this->pageCount; }
function getNextPageNo() { return $this->pageNo + 1; }
function hasPriorPage() { return $this->pageNo > 1; }
function getPriorPageNo() { return $this->pageNo - 1; }
function isFirstPage() { return $this->pageNo == 1 || $this->pageCount == 0; }
function isLastPage() { return $this->pageNo == $this->pageCount || $this->pageCount == 0; }
}
function load($con, $sql, $dataMaker, $pageSize, $pageNo) {
if ($pageSize < 1 || $pageNo < 1) return false;
// 1. 執行完整查詢取得總筆數
$rst = @mysql_query($sql, $con);
if (!$rst) return false;
$this->pageSize = $pageSize;
$this->pageNo = $pageNo;
$this->rowCount = @mysql_num_rows($rst);
$this->pageCount = (int)(($this->rowCount + $this->pageSize - 1) / $this->pageSize);
// 2. 移動指標至目標頁首筆
$this->currentPageStartNo = ($this->pageNo - 1) * $this->pageSize + 1;
$firstRowNo = $this->currentPageStartNo;
while (--$firstRowNo > 0 && @mysql_fetch_array($rst)); // 略過前幾頁資料
// 3. 讀取當前頁資料並轉換為物件
$read = 0;
$this->currentPageSize = 0;
while ($read < $this->pageSize && $row = @mysql_fetch_array($rst)) {
$this->records[$this->currentPageSize++] = $dataMaker($row);
$read++;
}
return true;
}
呼叫端需提供函數將關聯陣列轉為領域物件:
function makeUser($row) {
$u = new User();
$u->id = $row['id'];
$u->name = $row['username'];
return $u;
}
// 使用
$pager = new Pagination();
$pager->load($conn, "SELECT * FROM users", 'makeUser', 20, $_GET['p']);
foreach ($pager->records as $user) {
echo $user->name . '<br>';
}
// 導航
if ($pager->hasPriorPage()) echo '<a href="?p=' . $pager->getPriorPageNo() . '">上頁</a> ';
mysql_num_rows 需讀取全結果集,大表極耗記憶體;游標略過前頁資料效率低 (O(N))。SELECT COUNT(*) 取總數 + LIMIT offset, size 取分頁資料;或採用延遲關聯/游標分頁。@ 抑制錯誤,改用 PDOException 捕獲;支援 Generator 逐筆產出。