SubPages 類展示了一種經典的策略模式雛形:將分頁數據計算 (核心邏輯) 與HTML 渲染策略 (展示邏輯) 分離。構造函數接收 $subPage_type 參數 (1=簡潔模式, 2=經典數字模式),內部調用不同的私有渲染方法 (subPageCss1, subPageCss2)。這種設計允許在不修改核心計算邏輯的前提下,輕鬆擴展新的顯示樣式 (如 Bootstrap 分頁、AJAX 無刷新分頁、API JSON 輸出)。
function __construct($each_disNums, $nums, $current_page, $sub_pages, $subPage_link, $subPage_type) {
$this->each_disNums = intval($each_disNums); // 每頁條數
$this->nums = intval($nums); // 總條數
$this->current_page = $current_page ? intval($current_page) : 1; // 當前頁,默認 1
$this->sub_pages = intval($sub_pages); // 頁碼組顯示數量 (如一次顯示 10 個頁碼)
$this->pageNums = ceil($this->nums / $this->each_disNums); // 總頁數
$this->subPage_link = $subPage_link; // 分頁鏈接前綴 (如 "list.php?page=")
$this->show_SubPages($subPage_type); // 直接輸出 HTML (耦合輸出,見下文改進建議)
}
construct_num_Page()此算法解決「總頁數極大時,如何只顯示當前頁附近的固定數量頁碼」的問題。邏輯分三種情況:
1 ... $pageNums。$current_page <= 3):顯示 1, 2, ..., $sub_pages。$current_page > $pageNums - $sub_pages + 1):顯示最後 $sub_pages 頁 $pageNums-$sub_pages+1 ... $pageNums。$current_page-2 ... $current_page+7。
private function construct_num_Page() {
if ($this->pageNums < $this->sub_pages) {
// 情況 1
for ($i=0; $i<$this->pageNums; $i++) $current_array[$i] = $i+1;
} else {
// 情況 2, 3, 4
if ($this->current_page <= 3) {
for ($i=0; $i<$this->sub_pages; $i++) $current_array[$i] = $i+1;
} elseif ($this->current_page > $this->pageNums - $this->sub_pages + 1) {
for ($i=0; $i<$this->sub_pages; $i++) $current_array[$i] = $this->pageNums - $this->sub_pages + 1 + $i;
} else {
for ($i=0; $i<$this->sub_pages; $i++) $current_array[$i] = $this->current_page - 2 + $i;
}
}
return $current_array;
}
subPageCss1)適合移動端或側邊欄空間受限場景,僅顯示「首頁、上一頁、下一頁、尾頁」四個操作鏈接,不顯示具體頁碼數字。
/* 輸出示例:
共 4523 條記錄,每頁顯示 10 條,當前第 1/453 頁 [首頁] [上一頁] [下一頁] [尾頁]
*/
private function subPageCss1() {
$str = "共{$this->nums}條記錄,每頁顯示{$this->each_disNums}條,當前第{$this->current_page}/{$this->pageNums}頁 ";
// 首頁/上一頁
if ($this->current_page > 1) {
$str .= "[首頁] ";
$str .= "[上一頁] ";
} else {
$str .= "[首頁] [上一頁] ";
}
// 下一頁/尾頁
if ($this->current_page < $this->pageNums) {
$str .= "[下一頁] ";
$str .= "[尾頁] ";
} else {
$str .= "[下一頁] [尾頁] ";
}
echo $str;
}
subPageCss2)PC 端標準分頁體驗,包含頁碼數字組,當前頁高亮 (紅色加粗)。
/* 輸出示例:
當前第 1/453 頁 [首頁] [上一頁] 1 2 3 4 5 6 7 8 9 10 [下一頁] [尾頁]
*/
private function subPageCss2() {
$str = "當前第{$this->current_page}/{$this->pageNums}頁 ";
// 首頁/上一頁 (同模式一)
// ...
// 頁碼數字組
$pages = $this->construct_num_Page();
foreach ($pages as $p) {
if ($p == $this->current_page) {
$str .= "[{$p}]";
} else {
$str .= "[{$p}]";
}
}
// 下一頁/尾頁 (同模式一)
// ...
echo $str;
}
原類最大的問題在於構造函數中直接 echo 輸出 HTML,導致:
$subPage_link 直接拼接輸出,未轉義。
class Pagination
{
// ... 參數屬性、構造函數、construct_num_Page() 計算邏輯保持不變 ...
// 核心改動:移除 echo,返回結構化數據
public function getPaginationData(): array
{
$pages = $this->construct_num_Page();
$pageLinks = [];
foreach ($pages as $p) {
$pageLinks[] = [
'page' => $p,
'url' => $this->subPage_link . $p,
'is_current' => ($p == $this->current_page),
'label' => (string)$p,
];
}
return [
'total_items' => $this->nums,
'per_page' => $this->each_disNums,
'current_page' => $this->current_page,
'last_page' => $this->pageNums,
'first_page_url' => $this->pageNums > 0 ? $this->subPage_link . '1' : null,
'last_page_url' => $this->pageNums > 0 ? $this->subPage_link . $this->pageNums : null,
'prev_page_url' => $this->current_page > 1 ? $this->subPage_link . ($this->current_page - 1) : null,
'next_page_url' => $this->current_page < $this->pageNums ? $this->subPage_link . ($this->current_page + 1) : null,
'links' => $pageLinks, // 頁碼組詳情
'from' => $this->nums > 0 ? (($this->current_page - 1) * $this->each_disNums) + 1 : null,
'to' => min($this->current_page * $this->each_disNums, $this->nums),
];
}
}
// 控制器調用
$pagination = new Pagination($perPage, $total, $currentPage, 10, '?page=');
$data = $pagination->getPaginationData();
// 1. 模板渲染 (Smarty/Blade)
$tpl->assign('pagination', $data);
// 2. API 返回 JSON
return response()->json(['data' => $items, 'pagination' => $data]);
共 {$pagination.total_items} 條,第 {$pagination.current_page}/{$pagination.last_page} 頁
SubPages 類通過 construct_num_Page() 實現了經典的滑動窗口頁碼算法,並以策略模式支持雙渲染模式,邏輯清晰實用。但其直接在構造函數中輸出 HTML 的設計嚴重限制了現代化應用 (API、前後端分離、單元測試)。重構核心在於將渲染邏輯外移,類僅負責計算並返回標準化數據結構 (DTO),由視圖層或 API 序列化層決定最終輸出格式。這才是符合現代 PHP 開發規範 (PSR, SOLID) 的分頁組件設計。