簡介
分頁 是建立資料驅動應用程式時的一個重要概念。當從資料庫中提取記錄時,可能會擷取大量的記錄。例如,當針對作用中使用者或屬於特定位置的使用者執行查詢時,可能會傳回數百甚至數千個大量使用者。在單個網頁上顯示如此龐大數量的記錄並不是一個使用者友好的解決方案,因為這會讓使用者應接不暇,同時也會破壞使用者體驗的流暢度。
因此,一個較好的選擇是限制記錄的數量。這就是 分頁 的概念。換句話說,我們將記錄數量劃分為多個頁面,然後顯示該頁面。單個頁面可以有十個、十五個或任何其他可在前端顯示的合適記錄數量。
雖然分頁可以改善應用程式的整體使用者體驗,但它也可以讓應用程式運行得更快,因為我們可以檢索較少數量的記錄。因此,用戶端和伺服器之間在網路中傳輸的資料更少,從而減少了延遲時間。
在本教學中,我們將 建立一個 PHP 程式碼來連接到資料庫,並使用 MySQL 資料庫及其 LIMIT 子句來實作分頁.
先決條件
若要跟隨本教學,您將需要:
-
最新版本且已啟動運行的 Ubuntu。如果需要協助,請遵循 如何設定您的 Ubuntu 伺服器教學 。
-
您還需要安裝 PHP 和 MySQL。若要設定 PHP 和 MySQL,我們有一個教學:LAMP Stack setup – Linux Apache MySQL PHP.
步驟 1 — 設定資料庫使用者和測試資料庫
在本教學中,我們將與 MySQL 資料庫建立資料庫連線並獲取記錄。這些記錄將使用 table 元素顯示在 HTML 頁面上。為了建立連線並顯示記錄,我們將使用 PHP 指令碼。一旦我們準備好資料庫連線,我們將測試有分頁和沒有分頁的應用程式。以這種方式進行測試將使我們能夠了解分頁在實際中是如何運作的。
要連接到 MySQL 資料庫,我們需要一個範例 MySQL 資料庫以及用於連接到 MySQL 資料庫的使用者驗證資訊。在此步驟中,您將為您的 MySQL 資料庫建立一個非 root 使用者、一個範例資料庫以及一個用於測試 PHP 指令碼的資料表。
首先,登入您的伺服器。然後,使用以下命令登入 MySQL 伺服器:
|
1 |
mysql> sudo mysql -u root -p |
系統將提示您輸入 root 使用者的密碼。輸入密碼並按下 Enter 以繼續。接下來,建立一個名為 test_db 的範例資料庫,我們將在教學中使用它。若要建立新資料庫,請執行以下命令:
|
1 |
mysql> Create database test_db; |
您將在 MySQL 伺服器的輸出中看到有一行受到影響。接下來,我們需要為此資料庫建立一個新使用者。我們將授予此使用者所有權限。然而,在處理實際應用程式時,請確保限制其權限。我們將我們的使用者命名為 test_user。在以下命令中,將 PASSWORD 替換為強密碼:
|
1 |
mysql> GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'localhost' IDENTIFIED BY 'PASSWORD'; |
建立使用者後,請重新整理權限:
|
1 |
mysql> FLUSH PRIVILEGES; |
現在 test_user 和 test_db 都已準備就緒,請使用 test_db 來建立資料表。若要切換到 test_db,請執行以下命令:
|
1 |
mysql> Use test_db; |
一旦我們在輸出中看到資料庫已變更,我們就可以開始建立資料表了。我們將建立一個名為 Products 的新資料表來存放產品。對於我們的目的,我們在此資料表中只需要兩個資料欄: product_id 和 product_name。我們將設定 product_id 為 AUTO_INCREMENT,以便在每次添加新產品時自動遞增。另一個名為 product_name 的資料欄將用於儲存產品名稱。 product_name 資料欄將用於依名稱區分每個產品:
|
1 |
mysql> Create table products (product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50) NOT NULL ) Engine = InnoDB; |
現在我們將添加一些 產品 到這個新建立的資料表中。為此,請執行以下命令:
|
1 2 3 4 5 6 7 8 9 10 |
mysql> Insert into products(product_name) values ('WIRELESS MOUSE'); mysql> Insert into products(product_name) values ('BLUETOOTH SPEAKER'); mysql> Insert into products(product_name) values ('GAMING KEYBOARD'); mysql> Insert into products(product_name) values ('320GB FAST SSD'); mysql> Insert into products(product_name) values ('17 INCHES TFT'); mysql> Insert into products(product_name) values ('SPECIAL HEADPHONES'); mysql> Insert into products(product_name) values ('HD GRAPHIC CARD'); mysql> Insert into products(product_name) values ('80MM THERMAL PRINTER'); mysql> Insert into products(product_name) values ('HDMI TO VGA CONVERTER'); mysql> Insert into products(product_name) values ('FINGERPRINT SCANNER'); |
要驗證這些產品是否已輸入到資料表中,請執行以下命令:
|
1 |
mysql> select * from products; |
如果您看到上面輸入的產品,就表示一切準備就緒,可以繼續前進。使用以下命令退出 MySQL 資料庫:
|
1 |
mysql> quit; |
現在我們已經設定好了 MySQL 資料庫並輸入了測試資料,我們準備好編寫 PHP 腳本來連接到此資料庫並獲取記錄。
步驟 2 – 在不分頁的情況下獲取並顯示記錄
如上所述,我們將首先在不分頁的情況下顯示記錄。我們將建立一個 PHP 腳本,該腳本連接到 MySQL 資料庫並獲取記錄。我們將連接到上面建立的 test_db,並使用 test_user 來獲取記錄。
我們的 products 資料表目前只有十條記錄。對於許多使用者來說,可能不太明顯是否需要分頁。然而,在沒有分頁的情況下測試應用程式將詳細說明它如何有助於提升應用程式的整體體驗。我們也將了解分割資料如何有助於創造更好的使用者體驗並減輕伺服器的負擔。
在您的 PHP 伺服器上,於網站資料夾的網頁根目錄(document root)下,執行以下命令:
sudo nano /var/www/html/pagination_test.php
現在在此檔案中,添加以下內容。請確保將 PASSWORD 替換為密碼,其用於您的 test_user:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php try { $pdo = new PDO("mysql:host=localhost;dbname=test_db", "test_user", "PASSWORD"); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); $sql = "select * from products"; $stmt = $pdo->prepare($sql); $stmt -> execute(); echo "<table border='1' align='center'>"; while (($row = $stmt -> fetch(PDO::FETCH_ASSOC)) !== false) { echo "<tr>"; echo "<td>".$row['product_id']."</td>"; echo "<td>".$row['product_name']."</td>"; echo "</tr>"; } echo "</table>"; } catch(PDOException $e) { echo $e->getMessage(); } ?> |
儲存檔案。在我們繼續之前,我們將總結我們在上面所做的工作:
-
首先,我們連接到 MySQL 資料庫,為此我們使用了 PHP Data Object (PDO) 函式庫。我們使用上面用過的 MySQL 使用者憑證來連接到 MySQL 資料庫。PDO 是一個非常有用的函式庫,用於連接到資料庫。它使資料存取層易於編寫程式碼,並允許連接到不同的資料庫,而無需對應用程式進行廣泛的重構。PDO 使用預備陳述式(prepared statements),這確保了安全性不會受到損害。因此,查詢得以安全地執行。
-
接下來,我們使用了 PDO API 來執行 select * from products 陳述式。 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false) 確保 PHP 中的資料類型與資料庫中的相同。因此, product_id 和 product_name 分別顯示為整數和字串。
-
此 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 告訴 PDO 在發生錯誤時拋出異常。這樣一來,我們就可以輕鬆地在 try … catch 區塊中捕獲異常並根據需要進行處理。
現在我們的指令碼已經準備好了,我們必須執行它。為此,請打開您的瀏覽器並造訪以下網址: /var/www/html/pagination_test.php。請確保在網址中加上您的伺服器 IP。如果您是在本機執行,您的網址將變為 http://localhost/var/www/html/pagination_test.php.
您將會看到以下輸出:

在這裡,我們的產品已被傳回並顯示在頁面上。現在,想像一下如果我們有數百個產品。這將導致一個很長的迴圈來獲取資料並將其顯示在頁面上。這會增加網頁載入時間。
在下一節中,我們將修改 PHP 腳本並包含 MySQL LIMIT 子句。這將解決顯示大量記錄的問題。我們將添加分頁連結,以便使用者可以在頁面之間進行導航。
步驟 3 – 使用 PHP 設置分頁
在此步驟中,我們將使用 PHP 設置分頁,以使用多個表格來顯示資料。為了適應分頁,我們將修改在上一步中編寫的腳本。
我們將使用 LIMIT MySQL 資料庫的子句。在將其添加到腳本之前,讓我們看一個 MySQL LIMIT 語法的範例:
|
1 |
mysql> Select [column1, column2, column n...] from [table name] LIMIT offset, records; |
在上述語句中,我們可以看到 LIMIT 子句具有 offset 和 records 參數。 offset 告訴要跳過多少條記錄,而 records 則告訴每頁顯示或從資料庫中獲取的最大記錄數。
現在我們知道了分頁的工作原理,讓我們來看看我們將如何實現它。我們將每頁顯示三條記錄。因此,如果我們的資料庫中有十條記錄,我們將總記錄數除以每頁的記錄數,從而得到四個頁面。由於結果可能不是整數,我們將使用 PHP 的 Ceil 函數向上取整以獲得整數結果。以下是一個簡單的程式碼片段,用於演示 Ceil 函數:
|
1 |
$total_pages=ceil($total_records/$per_page); |
現在我們將添加分頁的程式碼。要啟用分頁並添加導航連結,請使用以下指令打開 /var/www/html/pagination_test.php 檔案:
|
1 |
$ sudo nano /var/www/html/pagination_test.php |
接下來,將此檔案的內容替換為以下程式碼:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<?php try { $pdo = new PDO("mysql:host=localhost;dbname=test_db", "test_user", "PASSWORD"); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); /* 開始分頁資訊 */ $page = 1; if (isset($_GET['page'])) { $page = filter_var($_GET['page'], FILTER_SANITIZE_NUMBER_INT); } $per_page = 3; $sqlcount = "select count(*) as total_records from products"; $stmt = $pdo->prepare($sqlcount); $stmt->execute(); $row = $stmt->fetch(); $total_records = $row['total_records']; $total_pages = ceil($total_records / $per_page); $offset = ($page-1) * $per_page; /* 結束分頁資訊 */ $sql = "select * from products limit :offset, :per_page"; $stmt = $pdo->prepare($sql); $stmt->execute(['offset'=>$offset, 'per_page'=>$per_page]); echo "<table border='1' align='center'>"; while ( ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) !== false) { echo "<tr>"; echo "<td>".$row['product_id']."</td>"; echo "<td>".$row['product_name']."</td>"; echo "</tr>"; } echo "</table>"; /* 開始導航 */ echo "<table border='1' align='center'>"; echo "<tr>"; if ($page-1 >= 1) { echo "<td><a href=".$_SERVER['PHP_SELF']."?page=".($page - 1).">上一頁</a></td>"; } if ($page+1 <= $total_pages) { echo "<td><a href=".$_SERVER['PHP_SELF']."?page=".($page + 1).">下一頁</a></td>"; } echo "</tr>"; echo "</table>"; /* 結束導航 */ } catch(PDOException $e) { echo $e->getMessage(); } ?> |
以下是此程式碼的摘要:
-
我們必須保留目前所在頁面的資訊。為此,我們使用 $page 變數。 $page 變數用於提取我們目前所在的頁面,透過 $_GET[‘page’] 變數。
-
接下來,我們需要指定每頁顯示多少筆資料。為此,我們使用 $per_page 變數。在這裡,我們每頁僅顯示三個產品。
-
如上所述,我們需要擁有資料庫中存在的記錄總數。這是必需的,以便我們能夠識別總頁數。 $total_records 變數保存了此資訊。
-
最後,我們需要 know 要跳過多少條記錄。例如,如果我們在第二頁,我們需要跳過資料庫的前三條記錄。我們正在使用 $offset 變數來保存此資訊。我們在每次載入頁面時使用以下公式計算此資訊: $offset=($page-1)*$per_page。如果您需要顯示任何其他數量的項目,您可以在 $per_page 變數中指定該值。
-
要顯示導覽按鈕,我們使用以下程式碼:
|
1 2 3 4 5 6 7 8 9 10 |
. . . if( $page-1>=1) { echo "<td><a href=".$_SERVER['PHP_SELF']."?page=".($page-1).">Previous</a></td>"; } if( $page+1<=$total_pages) { echo "<td><a href=".$_SERVER['PHP_SELF']."?page=".($page+1).">Next</a></td>"; } . . . |
其邏輯是, $page 用於保存當前頁面。如果我們想在頁面上顯示「上一頁」選項,腳本將從 $page 變數的值中減去 1。如果結果大於或等於 1,則會在頁面上顯示「上一頁」選項。
同樣地,要顯示「下一頁」選項,我們在 $page 變數上加 1。在這裡,我們要確保相加的結果不超過 $total_pages 變數中的總頁數。
之後,就該檢查頁面了。打開瀏覽器並使用您之前使用的 URL 導覽至該頁面:
|
1 |
http://your_server_ip/pagination_test.php |
您將看到如下輸出:



在這裡,您終於在 PHP 腳本中使用了 MySQL 的 LIMIT 子句實現了分頁。透過在您的應用程式中實現分頁,您將能以更好的方式在多條記錄之間進行導覽。
結論
在本教學中,我們介紹了如何在 Ubuntu 上使用 PHP 和 MySQL 實現分頁。利用這些步驟,您可以構建能夠妥善顯示大量記錄的應用程式,並將其劃分到各個頁面中以便進行有效操作。
此外,我們還有更多關於在 Ubuntu 上使用 PHP 和 MySQL 的實用教學:
- 在 Ubuntu 18.04 上安裝並保護 phpMyAdmin
- 如何重設 MariaDB 或 MySQL Root 密碼
- CloudSigma 教學:如何在伺服器上設定 MySQL 以及 MySQL 基礎知識
祝您使用愉快!
留言
目前尚無留言。成為第一個留言的人吧。