ThinkPHP 3.x 內建 Page 類功能基礎,但輸出 HTML 死板、難以整合 Bootstrap、不支援 AJAX、URL 規則固定。與其每次專案都重寫,不如封裝一個通用 mypage() 函式放入 Common/functions.php,專案間直接復用。
<?php
/**
* 通用分頁函式(放入 Common/functions.php)
* @param int $total 總筆數
* @param int $pageSize 每頁筆數
* @param string $paramName URL 參數名(預設 p)
* @param string $urlRule 自定義 URL 規則(支援 __PAGE__ 佔位符)
* @return void 透過 C() 寫入 limit 與 show 供模板直接使用
*/
function mypage(int $total, int $pageSize = 10, string $paramName = 'p', string $urlRule = '') {
// 1. 當前頁碼
$currentPage = max(1, (int)($_GET[$paramName] ?? 1));
// 2. 總頁數
$totalPages = max(1, (int)ceil($total / $pageSize));
if ($currentPage > $totalPages) $currentPage = $totalPages;
// 3. LIMIT 起始位移
$offset = ($currentPage - 1) * $pageSize;
$limit = "{$offset},{$pageSize}";
// 4. 計算上下頁
$prevPage = max(1, $currentPage - 1);
$nextPage = min($totalPages, $currentPage + 1);
// 5. 產生 URL 佔位符替換函式
$buildUrl = function ($page) use ($paramName, $urlRule) {
if ($urlRule) {
return str_replace('__PAGE__', $page, $urlRule);
}
// 預設:__SELF__ 為 ThinkPHP 當前 URL 常數
return __SELF__ . ($paramName ? "/{$paramName}/{$page}" : '');
};
// 6. 組裝 HTML(Bootstrap 4/5 相容)
$show = '';
// 7. 寫入配置供 Action/模板讀取
C('page_limit', $limit);
C('page_show', $show);
C('page_current', $currentPage);
C('page_total', $totalPages);
}
public function lists() {
$goods = M('Goods');
$where = ['is_pass' => 1, 'is_self' => 1];
$count = $goods->where($where)->count();
// 呼叫分頁函式
mypage($count, 5); // 每頁 5 筆
// 獲取 LIMIT 並查詢
$this->rows = $goods->where($where)
->limit(C('page_limit'))
->order('trade_num DESC, price ASC')
->select();
// 傳遞分頁 HTML 給模板
$this->assign('pageShow', C('page_show'));
$this->assign('pageCurrent', C('page_current'));
$this->assign('pageTotal', C('page_total'));
$this->display();
}
<div class="table-responsive">
<table class="table table-striped">
<thead><tr><th>ID</th><th>商品名</th><th>價格</th></tr></thead>
<tbody>
<volist name="rows" id="vo">
<tr><td>{$vo.id}</td><td>{$vo.name}</td><td>{$vo.price}</td></tr>
</volist>
</tbody>
</table>
</div>
<!-- 分頁導航 -->
<div class="mt-3">{$pageShow}</div>
<!-- 可選:頁碼資訊 -->
<small class="text-muted">第 {$pageCurrent} / {$pageTotal} 頁</small>
IS_AJAX,回傳 JSON:if (IS_AJAX) $this->ajaxReturn(['html' => $this->fetch('list_items'), 'page' => C('page_show')]);list_items.html。.pagination a 點擊,e.preventDefault(),$.get() 替換列表與分頁 HTML。新版框架內建強大分頁器(paginate()),支援 appends()、fragment()、onEachSide() 等鏈式配置,建議直接使用框架原生功能,無需手寫函式。本文方案適用於維護 ThinkPHP 3.x 老專案或理解分頁核心邏輯的教學場景。