分頁需三個關鍵參數:
$pageSize:每頁筆數$currentPage:當前頁碼(從 1 開始)$totalRows:總資料筆數衍生參數:
$offset = ($currentPage - 1) * $pageSize:起始位移$totalPages = ceil($totalRows / $pageSize):總頁數query('SELECT COUNT(*) FROM articles'); $totalRows = $stmt->fetchColumn(); $totalPages = (int)ceil($totalRows / $pageSize); // 取得當頁資料 $stmt = $pdo->prepare('SELECT * FROM articles ORDER BY id DESC LIMIT :offset, :pageSize'); $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); $stmt->bindValue(':pageSize', $pageSize, PDO::PARAM_INT); $stmt->execute(); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); return [ 'data' => $rows, 'pagination' => [ 'current_page' => $page, 'page_size' => $pageSize, 'total_rows' => $totalRows, 'total_pages' => $totalPages, 'has_prev' => $page > 1, 'has_next' => $page < $totalPages, ], ]; }
totalNum = $totalNum; $this->pageSize = $pageSize; $this->pageNo = max(1, $pageNo); $this->pageData = $pageData; $this->jsFunction = $jsFunction; $this->pageCount = max(1, (int)ceil($this->totalNum / $this->pageSize)); $this->pageNo = min($this->pageNo, $this->pageCount); $this->offset = ($this->pageNo - 1) * $this->pageSize; $this->hasPrev = $this->pageNo > 1; $this->hasNext = $this->pageNo < $this->pageCount; $this->pageList = $this->generatePageList(); } private function generatePageList(): array { $list = []; if ($this->pageCount <= 9) { $list = range(1, $this->pageCount); } else { if ($this->pageNo <= 4) { $list = array_merge(range(1, 5), [-1], [$this->pageCount]); } elseif ($this->pageNo > $this->pageCount - 4) { $list = array_merge([1], [-1], range($this->pageCount - 4, $this->pageCount)); } else { $list = array_merge( [1], [-1], range($this->pageNo - 2, $this->pageNo + 2), [-1], [$this->pageCount] ); } } return $list; } public function render(): string { if ($this->pageCount <= 1) return ''; $html = "<div class='pagination'><div class='page-bottom'>"; if ($this->hasPrev) { $html .= "<a class='page-prev' href='javascript:{$this->jsFunction}(" . ($this->pageNo - 1) . ")'>上一頁</a>"; } foreach ($this->pageList as $p) { if ($p === -1) { $html .= "<span class='page-break'>...</span>"; } elseif ($p == $this->pageNo) { $html .= "<span class='page-cur'>{$p}</span>"; } else { $html .= "<a href='javascript:{$this->jsFunction}({$p})'>{$p}</a>"; } } if ($this->hasNext) { $html .= "<a class='page-next' href='javascript:{$this->jsFunction}(" . ($this->pageNo + 1) . ")'>下一頁</a>"; } $html .= "</div></div>"; return $html; } }
prepare('SELECT * FROM news ORDER BY created_at DESC LIMIT :offset, :pageSize');
$stmt->execute(['offset' => $offset, 'pageSize' => $pageSize]);
$pageData = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 總筆數
$total = $pdo->query('SELECT COUNT(*) FROM news')->fetchColumn();
// 建立分頁器
$paginator = new Paginator($total, $pageSize, $pageNo, $pageData, 'loadPage');
// 輸出分頁 HTML
echo $paginator->render();
分頁核心在於 LIMIT offset, size 與總筆數查詢。封裝為可複用類別,支援伺服端渲染與 AJAX 兩種模式,並提供彈性的頁碼顯示演算法(省略號、邊界頁碼),能滿足大多數專案需求。