首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 分頁類完整實作:可配置主題、URL 參數保持、跳轉表單、SEO 友善

     編輯:PHP 綜合知識

類別設計目標

  • 支援自訂每頁筆數、顯示頁碼範圍、URL 額外參數
  • 靈活的模板主題系統(%upPage%、%linkPage% 等佔位符)
  • 自動處理當前 URL 參數合併與分頁參數分離
  • 支援「首頁/末頁/上一頁/下一頁」與數字頁碼、省略號
  • 可選頁碼跳轉表單(GET 表單保持其他查詢參數)
  • 零依賴、單檔案、易整合任意框架/原生專案

核心屬性

<?php
class Page {
    public $rollPage = 6;      // 分頁欄顯示頁碼數
    public $parameter = '';    // 額外 URL 參數字串
    public $listRows = 20;     // 每頁筆數
    public $firstRow = 0;      // 起始行數 (LIMIT offset)
    
    protected $totalPages = 0; // 總頁數
    protected $totalRows = 0;  // 總筆數
    protected $nowPage = 1;    // 當前頁
    protected $coolPages = 0;  // 分頁組數
    
    protected $config = [
        'redirect' => false,           // 是否顯示跳轉表單
        'header'   => '條記錄',        // 總筆數標籤
        'prev'     => '上一頁',
        'next'     => '下一頁',
        'first'    => '1',
        'last'     => '最後一頁',
        'theme'    => '<div class="pagination">%upPage% %first% %prePage% %linkPage% %nextPage% %downPage%</div> <div class="pagination-info">共 %totalPage% 頁</div>'
    ];
    
    protected $varPage = 'p';  // 分頁參數名
    // ...
}
?>

建構子邏輯

<?php
public function __construct($totalRows, $listRows = '', $parameter = '') {
    $this->totalRows = (int)$totalRows;
    $this->parameter = $parameter;
    $this->varPage = defined('VAR_PAGE') ? VAR_PAGE : 'p'; // 支援常數覆寫
    
    if ($listRows) $this->listRows = (int)$listRows;
    
    $this->totalPages = ceil($this->totalRows / $this->listRows);
    $this->coolPages  = ceil($this->totalPages / $this->rollPage);
    
    // 當前頁驗證
    $this->nowPage = isset($_GET[$this->varPage]) ? max(1, (int)$_GET[$this->varPage]) : 1;
    if ($this->totalPages > 0 && $this->nowPage > $this->totalPages) {
        $this->nowPage = $this->totalPages;
    }
    
    $this->firstRow = $this->listRows * ($this->nowPage - 1); // LIMIT 起始位置
}
?>

核心輸出方法 show()

<?php
public function show() {
    if ($this->totalRows === 0) return '';
    
    // 1. 處理 URL 參數:移除分頁參數,保留其他
    $p = $this->varPage;
    $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);
    }
    
    // 2. 計算顯示頁碼範圍
    if ($this->totalPages <= $this->rollPage) {
        $start = 1; $end = $this->totalPages;
    } else {
        if ($this->nowPage <= $this->rollPage - 1) {
            $start = 1; $end = $this->rollPage; $isLast = true;
        } elseif ($this->nowPage > $this->totalPages - $this->rollPage + 1) {
            $start = $this->totalPages - $this->rollPage + 1; $end = $this->totalPages; $isFirst = true;
        } else {
            $size = (int)($this->rollPage / 2);
            $start = $this->nowPage - $size; $end = $this->nowPage + $size;
            $isFirst = $isLast = true;
        }
    }
    
    // 3. 組裝各區塊 HTML
    $upRow = $this->nowPage - 1;
    $downRow = $this->nowPage + 1;
    
    $theFirst = $isFirst ? "<a class='first' href='{$url}&{$p}=1'>{$this->config['first']}</a>" : '';
    $theEnd   = $isLast  ? "<a class='last' href='{$url}&{$p}={$this->totalPages}'>{$this->config['last']}</a>" : '';
    $upPage   = $upRow > 0 ? "<a class='prev' href='{$url}&{$p}={$upRow}'>{$this->config['prev']}</a>" : '';
    $downPage = $downRow <= $this->totalPages ? "<a class='next' href='{$url}&{$p}={$downRow}'>{$this->config['next']}</a>" : '';
    
    $linkPage = '';
    if ($start == 3) $linkPage .= "<a href='{$url}&{$p}=2'>2</a>";
    if ($start >= 4) $linkPage .= "<a href='{$url}&{$p}=2'>2</a><span class='ellipsis'>...</span>";
    
    for ($i = $start; $i <= $end; $i++) {
        if ($i != $this->nowPage) {
            $linkPage .= " <a href='{$url}&{$p}={$i}'>{$i}</a>";
        } else {
            $linkPage .= " <span class='current'>{$i}</span>";
        }
        if ($i == $end && $i < $this->totalRows) {
            $linkPage .= " <span class='ellipsis'>...</span>";
        }
    }
    
    // 4. 替換主題佔位符
    $pageStr = str_replace(
        ['%header%','%nowPage%','%totalRow%','%totalPage%','%upPage%','%first%','%prePage%','%linkPage%','%nextPage%','%downPage%','%end%'],
        [$this->config['header'],$this->nowPage,$this->totalRows,$this->totalPages,$upPage,$theFirst,'',$linkPage,'',$downPage,$theEnd],
        $this->config['theme']
    );
    
    // 5. 可選跳轉表單
    if ($this->config['redirect'] && $this->totalPages > 1) {
        $redirect = "<form method='get' action=''>到第 <input name='{$p}' type='text' size='3' maxlength='3' value='{$this->nowPage}'/> 頁 <input type='submit' value='確定'/>";
        if (!empty($params)) {
            foreach ($params as $k => $v) {
                $redirect .= "<input type='hidden' name='{$k}' value='{$v}'/>";
            }
        }
        $redirect .= "</form>";
        $pageStr .= $redirect;
    }
    
    return $pageStr;
}
?>

使用範例

<?php
// 1. 取得總筆數
$total = $pdo->query('SELECT COUNT(*) FROM articles WHERE status=1')->fetchColumn();

// 2. 實例化分頁類
$page = new Page($total, 15, '&category=tech&sort=desc'); // 每頁 15 筆,保留分類/排序參數
$page->setConfig('theme', '<nav aria-label="Page navigation">%upPage% %linkPage% %downPage%</nav>');
$page->setConfig('prev', '«');
$page->setConfig('next', '»');
$page->setConfig('redirect', true); // 啟用跳轉表單

// 3. 查詢當頁資料
$offset = $page->firstRow;
$limit  = $page->listRows;
$articles = $pdo->query("SELECT * FROM articles WHERE status=1 ORDER BY id DESC LIMIT $offset, $limit")->fetchAll();

// 4. 模板輸出
?>
<div class="articles">
    <?php foreach ($articles as $art): ?>
        <article><h2><?= htmlspecialchars($art['title']) ?></h2></article>
    <?php endforeach; ?>
</div>
<?= $page->show() ?>

CSS 樣式建議

.pagination { display: flex; gap: 4px; align-items: center; margin: 16px 0; }
.pagination a, .pagination span { padding: 6px 12px; border: 1px solid #ddd; border-radius: 4px; text-decoration: none; color: #333; }
.pagination a:hover { background: #f5f5f5; }
.pagination .current { background: #007bff; color: #fff; border-color: #007bff; }
.pagination .ellipsis { border: none; color: #999; }
.pagination-info { color: #666; font-size: 0.9em; }
.pagination form { display: inline-flex; gap: 4px; align-items: center; margin-left: 16px; }
.pagination input[type=text] { width: 40px; text-align: center; }

SEO 與無障礙加強

擴充建議

  1. 快取總筆數:高流量場景將 `COUNT(*)` 結果快取 30-60 秒(Redis)。
  2. 游標分頁:大資料集改用 `WHERE id > $lastId ORDER BY id LIMIT $size`,避免 `OFFSET` 深分頁效能問題。
  3. AJAX 分頁:`show()` 輸出 JSON 結構 `{html:'...', current:3, total:10}`,前端局部更新。
  4. 多語系:`config` 文字從語言包讀取。

總結

這個 `Page` 類提供生產級分頁功能:參數自動保持、主題高度可配、跳轉表單、SEO 標記友善。核心邏輯集中於 `show()` 方法的 URL 處理、頁碼範圍計算與模板替換,易於理解與二次開發。實務中建議搭配快取總數、游標分頁等優化策略應對大數據場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved