ThinkPHP 3.2 內建 Page 類不支援 AJAX。本文實作 AjaxPage 類,繼承原分頁邏輯、輸出 JS 呼叫連結,配合 jQuery .load()/.get() 實現無刷新分頁。
Lib/ORG/Util/AjaxPage.class.php<?php
class AjaxPage {
public $rollPage = 5; // 分頁欄顯示頁數
public $parameter = ''; // 額外 URL 參數
public $listRows = 20; // 每頁筆數
public $firstRow = 0; // 起始行
protected $totalPages = 0;
protected $totalRows = 0;
protected $nowPage = 1;
protected $coolPages = 0;
protected $config = [
'header' => '條記錄', 'prev' => '上一頁', 'next' => '下一頁',
'first' => '第一頁', 'last' => '最後一頁',
'theme' => ' %totalRow% %header% %nowPage%/%totalPage% 頁 %upPage% %downPage% %first% %prePage% %linkPage% %nextPage% %end%',
];
protected $varPage = 'p';
protected $ajaxFunc = '';
public function __construct(int $totalRows, int $listRows = '', string $ajaxFunc, string $parameter = '') {
$this->totalRows = $totalRows;
$this->ajaxFunc = $ajaxFunc;
$this->parameter = $parameter;
$this->varPage = C('VAR_PAGE') ?: 'p';
$this->listRows = $listRows ?: $this->listRows;
$this->totalPages = ceil($this->totalRows / $this->listRows);
$this->coolPages = ceil($this->totalPages / $this->rollPage);
$this->nowPage = !empty($_GET[$this->varPage]) ? intval($_GET[$this->varPage]) : 1;
if ($this->nowPage > $this->totalPages) $this->nowPage = $this->totalPages;
$this->firstRow = $this->listRows * ($this->nowPage - 1);
}
public function setConfig(string $name, string $value): void {
if (isset($this->config[$name])) $this->config[$name] = $value;
}
public function show(): string {
if ($this->totalRows === 0) return '';
$p = $this->varPage;
$nowCoolPage = ceil($this->nowPage / $this->rollPage);
$url = $_SERVER['REQUEST_URI'] . (strpos($_SERVER['REQUEST_URI'], '?') ? '' : '?') . $this->parameter;
$parse = parse_url($url);
if (isset($parse['query'])) {
parse_str($parse['query'], $params);
unset($params[$p]);
$url = $parse['path'] . '?' . http_build_query($params);
}
// 上一頁
$upRow = $this->nowPage - 1;
$upPage = $upRow > 0
? "".$this->config['prev'].""
: '';
// 下一頁
$downRow = $this->nowPage + 1;
$downPage = $downRow <= $this->totalPages
? "".$this->config['next'].""
: '';
// 首頁/上一組
if ($nowCoolPage == 1) {
$theFirst = $prePage = '';
} else {
$preRow = $this->nowPage - $this->rollPage;
$prePage = "上{$this->rollPage}頁";
$theFirst = "".$this->config['first']."";
}
// 尾頁/下一組
if ($nowCoolPage == $this->coolPages) {
$nextPage = $theEnd = '';
} else {
$nextRow = $this->nowPage + $this->rollPage;
$nextPage = "下{$this->rollPage}頁";
$theEnd = "".$this->config['last']."";
}
// 數字頁碼
$linkPage = '';
for ($i = 1; $i <= $this->rollPage; $i++) {
$page = ($nowCoolPage - 1) * $this->rollPage + $i;
if ($page > $this->totalPages) break;
if ($page != $this->nowPage) {
$linkPage .= " $page ";
} else {
$linkPage .= " $page ";
}
}
return str_replace(
['%header%','%nowPage%','%totalRow%','%totalPage%','%upPage%','%downPage%','%first%','%prePage%','%linkPage%','%nextPage%','%end%'],
[$this->config['header'],$this->nowPage,$this->totalRows,$this->totalPages,$upPage,$downPage,$theFirst,$prePage,$linkPage,$nextPage,$theEnd],
$this->config['theme']
);
}
}
?>
UserAction.class.php<?php
class UserAction extends Action {
public function user() {
import('ORG.Util.AjaxPage');
$model = M('user');
$count = $model->count();
$page = new AjaxPage($count, 5, 'user'); // 第3參數 = JS 函數名
$limit = $page->firstRow . ',' . $page->listRows;
$list = $model->order('id desc')->limit($limit)->select();
$this->assign('list', $list);
$this->assign('page', $page->show());
$this->display();
}
}
?>
Tpl/User/user.html<html>
<head>
<title>AJAX 無刷新分頁</title>
<script src="__PUBLIC__/jquery-1.7.2.min.js"></script>
<script>
function user(page) {
$.get('__URL__/user', {p: page}, function(html) {
$('#user').replaceWith('' + html + '');
});
}
</script>
</head>
<body>
<div id="user">
<volist name="list" id="vo">
{$vo.id} {$vo.username}<br/>
</volist>
{$page}
</div>
</body>
</html>
href='javascript:user(2)',而非 URL。new AjaxPage(..., 'user') → function user(page)。id="user"、JS $('#user')、回傳 HTML 重新包裝 <div id="user">。{p: page} 對應 ThinkPHP VAR_PAGE 設定。function user(page) {
$('#user').addClass('loading');
$.post('__URL__/user', {p: page}, function(html) {
$('#user').removeClass('loading').replaceWith('' + html + '');
}).fail(function() {
$('#user').removeClass('loading').append('載入失敗,請重試');
});
}
核心思想:分頁類輸出 JS 呼叫 → 前端攔截點擊 → AJAX 請求局部刷新。此模式可移植至 ThinkPHP 5/6、Laravel 等框架,只需調整分頁類輸出格式與路由對應。