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

PHP 分頁類庫實作指南:支援 URL 參數保留、下拉跳頁、自訂樣式

     編輯:PHP 相關知識

前言

分頁是 Web 開發最基礎也最常見的功能。一個好的分頁類別應具備:自動保留原有查詢參數、支援首頁/尾頁/上下頁/數字頁碼/下拉跳頁、全域變數隔離不污染命名空間、可自訂 HTML 結構與 CSS 樣式。本文提供一個生產級的 PageDivide 函式完整實作與使用教學。

完整實作程式碼(pageDivide.php)

<?php
/**
 * 通用分頁函式
 * @param int   $total    總筆數
 * @param int   $shownu   每頁筆數,預設 20
 * @param string $url     目標 URL,留空自動偵測 $_SERVER['REQUEST_URI']
 * @return void  透過全域變數 $page, $sqlfirst, $pagecon 輸出結果
 */
function pageDivide(int $total, int $shownu = 20, string $url = ''): void {
    // 靜態快取每頁筆數,供其他地方(如 SQL LIMIT)使用
    $GLOBALS['shownu'] = $shownu;

    // 1. 目前頁碼
    $page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;

    // 2. 目標 URL 處理:保留原有查詢參數,移除舊 page 參數
    if (!$url) {
        $url = $_SERVER['REQUEST_URI'] ?? '';
    }
    $parsed = parse_url($url);
    $query = $parsed['query'] ?? '';
    
    if ($query) {
        // 移除舊的 page=xxx
        $query = preg_replace('/(&?)page=\d+/', '', $query);
        $query = trim($query, '&');
        $url = str_replace($parsed['query'], $query, $url);
        $separator = $query ? '&' : '?';
    } else {
        $separator = '?';
    }
    $url .= $separator . 'page=';

    // 3. 分頁計算
    $lastpg = (int)ceil($total / $shownu);      // 總頁數
    $page = min($page, $lastpg);                // 修正超出範圍
    $prepg = $page - 1;                         // 上一頁
    $nextpg = ($page == $lastpg) ? 0 : $page + 1; // 下一頁(0 表示無)
    $sqlfirst = ($page - 1) * $shownu;          // SQL LIMIT 起始位移

    // 4. 組裝分頁導航 HTML
    $pagecon = "顯示第 " . ($total ? $sqlfirst + 1 : 0) . "-" . min($sqlfirst + $shownu, $total) . " 筆,共 $total 筆";

    if ($lastpg <= 1) {
        $GLOBALS['page'] = $page;
        $GLOBALS['sqlfirst'] = $sqlfirst;
        $GLOBALS['pagecon'] = $pagecon;
        return; // 單頁直接返回
    }

    // 首頁 / 上一頁
    $pagecon .= $page != 1 ? " 首頁 " : " 首頁 ";
    $pagecon .= $prepg ? " 上一頁 " : " 上一頁 ";

    // 數字頁碼(可選:只顯示當前頁前後各 2 頁)
    $window = 2;
    $start = max(1, $page - $window);
    $end = min($lastpg, $page + $window);
    for ($i = $start; $i <= $end; $i++) {
        if ($i == $page) {
            $pagecon .= " $i ";
        } else {
            $pagecon .= " $i ";
        }
    }

    // 下一頁 / 尾頁
    $pagecon .= $nextpg ? " 下一頁 " : " 下一頁 ";
    $pagecon .= $page != $lastpg ? " 尾頁 " : " 尾頁 ";

    // 下拉跳頁選單
    $pagecon .= " 跳至  頁,共 $lastpg 頁";

    // 5. 寫入全域變數供呼叫端使用
    $GLOBALS['page'] = $page;
    $GLOBALS['sqlfirst'] = $sqlfirst;
    $GLOBALS['pagecon'] = $pagecon;
}

使用範例(MVC 控制器中)

<?php
require_once 'pageDivide.php';

// 1. 取得總筆數(建議用 COUNT(*) 而非 fetch_all 再 count)
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->query("SELECT COUNT(*) FROM articles WHERE status = 1");
$total = (int)$stmt->fetchColumn();

// 2. 呼叫分頁函式
pageDivide($total, 10); // 每頁 10 筆

// 3. 取得分頁參數執行查詢
$page = $GLOBALS['page'];
$offset = $GLOBALS['sqlfirst'];
$limit = $GLOBALS['shownu'];

$stmt = $pdo->prepare("SELECT * FROM articles WHERE status = 1 ORDER BY id DESC LIMIT ?, ?");
$stmt->bindValue(1, $offset, PDO::PARAM_INT);
$stmt->bindValue(2, $limit, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 4. 輸出資料
foreach ($rows as $row) {
    echo "
{$row['title']}
"; } // 5. 輸出分頁導航 echo $GLOBALS['pagecon'];

進階客製化:注入樣式與結構

若專案使用 Bootstrap 5,可修改組裝 HTML 區段:


// 替換原本的字串拼接為:
$pagecon = "";

常見問題與解決方案

問題原因解決
分頁連結遺失原有查詢參數(如 ?keyword=php)URL 重組時未正確保留 query string使用 parse_url + preg_replace 精確移除舊 page 參數,其餘保留
最後一頁資料筆數不足導致 offset 越界未對 $page 做 min($lastpg) 修正函式內已內建 $page = min($page, $lastpg)
多語系專案需調整文字字串硬編碼在函式內將文字提取為陣列參數或語系檔,函式接受 $lang 參數
API 回傳 JSON 需要分頁中繼資料而非 HTML函式直接輸出 HTML重構為回傳陣列 ['current'=>$page, 'total'=>$lastpg, 'per_page'=>$shownu, 'links'=>[...]]

結語

pageDivide 以單一函式封裝「計算、URL 處理、HTML 產生」三大職責,適合中小型專案快速整合。大型專案建議採用 分頁器物件(Paginator) 模式(如 Laravel LengthAwarePaginator),支援多種呈現層(HTML、JSON、API Resource)並易於單元測試。

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