class Pager {
public $sql, $datanum, $page_size;
private $_conn, $_query_id, $_errstr;
public function __construct($sql, $page_size) {
$result = mysql_query($sql);
$this->datanum = mysql_num_rows($result);
$this->sql = $sql;
$this->page_size = $page_size;
}
// 當前頁碼(從 QUERY_STRING 解析)
public function page_id() {
if (empty($_SERVER['QUERY_STRING'])) return 1;
if (strpos($_SERVER['QUERY_STRING'], 'page_id=') === false) return 1;
return (int)substr($_SERVER['QUERY_STRING'], 8);
}
// 剩餘 URL 參數(保留其他查詢條件)
public function url() {
if (empty($_SERVER['QUERY_STRING'])) return '';
if (strpos($_SERVER['QUERY_STRING'], 'page_id=') === false)
return '&' . $_SERVER['QUERY_STRING'];
return str_replace('page_id=' . $this->page_id(), '', $_SERVER['QUERY_STRING']);
}
// 總頁數
public function page_num() {
return $this->datanum == 0 ? 1 : ceil($this->datanum / $this->page_size);
}
// LIMIT 偏移量
public function start() {
return ($this->page_id() - 1) * $this->page_size;
}
// 帶 LIMIT 的查詢 SQL
public function sqlquery() {
return $this->sql . " LIMIT " . $this->start() . ", " . $this->page_size;
}
// 生成分頁導航 HTML
public function set_page_info() {
$html = "共 {$this->datanum} 條 ";
$html .= $this->link(1, '首頁');
$html .= $this->page_id() == 1 ? '上一頁' : $this->link($this->page_id() - 1, '上一頁');
$html .= $this->page_numbers();
$html .= $this->page_id() == $this->page_num() ? '下一頁' : $this->link($this->page_id() + 1, '下一頁');
$html .= $this->link($this->page_num(), '尾頁');
$html .= " 第 {$this->page_id()} / {$this->page_num()} 頁";
return $html;
}
private function link($page, $text) {
return '' . $text . ' ';
}
private function page_numbers() {
$total = $this->page_num();
$current = $this->page_id();
$html = '';
if ($total <= 10) {
for ($i = 1; $i <= $total; $i++) $html .= $this->link($i, $i);
} elseif ($current <= 6) {
for ($i = 1; $i <= 10; $i++) $html .= $this->link($i, $i);
} elseif ($total - $current >= 4) {
for ($i = $current - 5; $i <= $current + 4; $i++) $html .= $this->link($i, $i);
} else {
for ($i = $total - 9; $i <= $total; $i++) $html .= $this->link($i, $i);
}
return $html;
}
}
require 'Pager.class.php';
$conn = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('db', $conn);
mysql_query('SET NAMES utf8');
$sql = "SELECT word FROM spam_accuse_word_list WHERE flag='0'";
$pager = new Pager($sql, 20);
$result = mysql_query($pager->sqlquery());
while ($row = mysql_fetch_assoc($result)) {
echo $row['word'] . '
';
}
echo $pager->set_page_info();
-- 第 1 頁:LIMIT 0, 10 -- 第 2 頁:LIMIT 10, 10 -- 第 n 頁:LIMIT (n-1)*size, size SELECT * FROM table LIMIT (),
function loadPage(page) {
$.get('ajax_list.php', {page: page, size: 20}, function(html) {
$('#list').html(html.list);
$('#pager').html(html.pager);
}, 'json');
}
$(document).on('click', '.page-link', function(e) {
e.preventDefault();
loadPage($(this).data('page'));
});
$page = max(1, (int)($_GET['page'] ?? 1));
$size = min(100, max(1, (int)($_GET['size'] ?? 20)));
$offset = ($page - 1) * $size;
$total = (int)mysql_result(mysql_query("SELECT COUNT(*) FROM message"), 0);
$pages = ceil($total / $size);
$data = mysql_query("SELECT * FROM message ORDER BY id DESC LIMIT $offset, $size");
$list = '';
while ($row = mysql_fetch_assoc($data)) {
$list .= "{$row['title']} - {$row['content']}";
}
// 生成分頁 HTML(同 Pager 類邏輯,輸出字符串)
$pagerHtml = generatePagerHtml($page, $pages, $_SERVER['REQUEST_URI']);
echo json_encode(['list' => $list, 'pager' => $pagerHtml, 'total' => $total]);
$pageSize = 2;
$url = $_SERVER['REQUEST_URI'];
$parsed = parse_url($url);
$path = $parsed['path']; // 去除查詢字符串
$total = mysql_result(mysql_query("SELECT COUNT(*) FROM message"), 0);
$totalPages = ceil($total / $pageSize);
$page = isset($_GET['page']) ? max(1, min((int)$_GET['page'], $totalPages)) : 1;
$offset = ($page - 1) * $pageSize;
$result = mysql_query("SELECT * FROM message LIMIT $offset, $pageSize");
// ... 輸出數據 ...
// 簡易分頁鏈接
for ($i = 1; $i <= $totalPages; $i++) {
$qs = http_build_query(array_merge($_GET, ['page' => $i]));
echo "$i ";
}
| 維度 | 方案一:類封裝 | 方案二:AJAX | 方案三:原生輕量 |
|---|---|---|---|
| 代碼復用性 | 高(類封裝) | 中(需前後端協作) | 低(邏輯分散) |
| 用戶體驗 | 頁面跳轉 | 無刷新,流暢 | 頁面跳轉 |
| SEO 友好 | 佳(獨立 URL) | 需額外處理(History API/SSR) | 佳 |
| 適用場景 | 後台管理、內容列表 | 前台列表、無限滾動預載 | 簡單項目、快速原型 |
| 維護成本 | 低 | 中 | 高(邏輯重複) |
COUNT(*) 慢,考慮緩存總數、觸發器維護計數表、或 EXPLAIN 估算行數LIMIT 100000, 20 掃描 10 萬行,改用 WHERE id > last_id LIMIT 20(游標分頁)PHP 分頁核心是 LIMIT offset, size。方案一類封裝適合傳統多頁應用,代碼復用性強;方案二AJAX提升前端體驗,配合 History API 解決 SEO;方案三原生邏輯適合快速驗證。生產環境務必關注深分頁性能、計數緩存、索引設計三大塊,並根據業務選型。