[PHP] Thuật toán phân trang, hướng dẫn làm chức năng phân trang trong PHP

Đăng bởi: Admin | View: 3591 | Chuyên đề: PHP

Phân trang căn bản là tiến trình lấy một tập hợp các kết quả & phân chia thành các trang để dễ xem hơn.Với những trang Website có dữ liệu lớn, việc phân trang là rất trọng yếu, nó giúp trang website sẽ load mau hơn , giúp người dùng đơn giản nhấn chọn trang mà mình mong chờ, đến được trang có bài viết mà mình cần, cực kỳ nhanh chóng, đơn giản & chuẩn xác.

Phân trang căn bản là tiến trình lấy một tập hợp các kết quả & phân chia thành các trang để dễ xem hơn.Với những trang Website có dữ liệu lớn, việc phân trang là rất trọng yếu, nó giúp trang website sẽ load mau hơn , giúp người dùng đơn giản nhấn chọn trang mà mình mong chờ, đến được trang có bài viết mà mình cần, cực kỳ nhanh chóng, đơn giản & chuẩn xác. Trong nội dung này vncoder.vn sẽ đặt ra sáng tạo thuật toán & hướng dẫn làm chức năng phân trang trong PHP.

Sáng tạo thuật toán phân trang

Trường hợp 1: Phân trang cho bảng tin tức & tổng số records là 1000. Yêu cầu phân trang với mỗi trang 10 records.

Với trường hợp này ta có tổng số trang là 1000/10 = 100. Nhưng vấn đề là làm thế nào để truy vấn lấy ra các records tương ứng với mỗi trang? Để khắc phục vấn đề này thì ta sử dụng LIMIT trong MySQL. Như thế câu truy vấn cho từng trang sẽ như sau:

  • Trang 01: SELECT * FROM NEWS LIMIT 0, 10
  • Trang 02: SELECT * FROM NEWS LIMIT 10, 10
  • Trang 03: SELECT * FROM NEWS LIMIT 20, 10
  • Trang 04: SELECT * FROM NEWS LIMIT 30, 10

Trường hợp tổng số trang là số lẻ & không chia hết cho số records trên một trang thì ta phải làm tròn phép chia ở cận trên.

Chẳng hạn: Tổng số records là 22, số records trên một trang là 10 thì tổng số trang là 22/10 = 2.2, làm tròn lên sẽ là 3.

Lúc này là làm thế nào để xác nhận các con số màu đỏ ở các câu truy vấn trên? Các con số màu đỏ ta gọi là start.

Xem Thêm  Lớp trong Java - javatpoint - lớp đối tượng trong java với ví dụ

Khái niệm:

  • total_record: tổng số records
  • current_page: trang hiện thời
  • limit: số records hiển thị trên mỗi trang
  • start: record khởi đầu trong câu lệnh SQL

& đây là phương pháp tính start:

  • Trang 01: start = (1 – 1) * 10 =  0, tương tự với (current_page – 1) * limit.
  • Trang 02: start = (2 – 1) * 10 = 10, tương tự với (current_page – 1) * limit.
  • Trang 03: start = (3 – 1) * 10 = 20, tương tự với (current_page – 1) * limit.
  • Trang 04: start = (4 – 1) * 10 = 30, tương tự với (current_page – 1) * limit.

Như thế thuật toán chung để tính start này là: start = (current_page – 1) * limit.

Hướng dẫn phân trang bằng PHP

Từ suy luận ở trên ta thấy để phân trang thì phải biết các tham số:

  • Tổng số records: Ta dùng lệnh count trong MySQL.
  • Trang hiện thời: Dựa theo tham số page trên URL.
  • Số records trong mỗi trang: Tham số do coder tự truyền vào.

Để rõ hơn thì ta sẽ làm một chẳng hạn sử dụng MySQL & PHP để phân trang luôn. 

Tạo database:

Bạn tạo một database tên là paging_example & sau đó chạy câu lệnh SQL sau:

CREATE TABLE IF NOT EXISTS `news` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=46 ;

Câu lệnh này sẽ tạo một table tên là news. Kế tiếp ta insert vào một số dữ liệu để chạy dùng thử.

INSERT INTO `news` (`id`, `title`) VALUES
(1, 'Title 1'),
(2, 'Title 2'),
(3, 'Title 3'),
(4, 'Title 4'),
(5, 'Title 5'),
(6, 'Title 6'),
(7, 'Title 7'),
(8, 'Title 8'),
(9, 'Title 9'),
(10, 'Title 10'),
(11, 'Title 11'),
(12, 'Title 12'),
(13, 'Title 13'),
(14, 'Title 14'),
(15, 'Title 15'),
(16, 'Title 16'),
(17, 'Title 17'),
(18, 'Title 18'),
(19, 'Title 19'),
(20, 'Title 20'),
(21, 'Title 21'),
(22, 'Title 22'),
(23, 'Title 23'),
(24, 'Title 24'),
(25, 'Title 25'),
(26, 'Title 26'),
(27, 'Title 27'),
(28, 'Title 28'),
(29, 'Title 29'),
(30, 'Title 30'),
(31, 'Title 31'),
(32, 'Title 32'),
(33, 'Title 33'),
(34, 'Title 34'),
(35, 'Title 35'),
(36, 'Title 36'),
(37, 'Title 37'),
(38, 'Title 38'),
(39, 'Title 39'),
(40, 'Title 40'),
(41, 'Title 41'),
(42, 'Title 42'),
(43, 'Title 43'),
(44, 'Title 44'),
(45, 'Title 45');

Tạo layout:

Bạn tạo một file tên là index.php & sau đó sao chép đoạn mã HTML dưới đây:

<!DOCTYPE htmlvàgt;
<htmlvàgt;
    <headvàgt;
        <titlevàgt;Chẳng hạn phân trang trong PHP & MySQLvàlt;/titlevàgt;
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </headvàgt;
    <bodyvàgt;
        <?php 
        // PHẦN XỬ LÝ PHP
        ?>
        <divvàgt;
            <?php 
            // PHẦN HIỂN THỊ TIN TỨC
            ?>
        </divvàgt;
        <div class="pagination">
           <?php 
            // PHẦN HIỂN THỊ PHÂN TRANG
           ?>
        </divvàgt;
    </bodyvàgt;
</htmlvàgt;

Trong layout chia làm 3 phần như sau:

  • PHẦN XỬ LÝ PHP
  • PHẦN HIỂN THỊ TIN TỨC
  • PHẦN HIỂN THỊ PHÂN TRANG
Xem Thêm  Truy cập phần tử trong danh sách python - phần tử truy cập danh sách python

Lúc này ta code cho từng phần nhé.

Phần giải quyết PHP: Phần này giải quyết truy vấn DataBase & thuật toán phân trang, phần này khá trọng yếu bởi nó tính toán các thông số kỹ thuật phân trang & khởi tạo các biến sử dụng cho các phần sót lại.

// PHẦN XỬ LÝ PHP
// BƯỚC 1: KẾT NỐI DataBase
$conn = mysqli_connect('localhost', 'root', '', 'paging_example');
 
// BƯỚC 2: TÌM TỔNG SỐ RECORDS
$result = mysqli_query($conn, 'select count(id) as total from news');
$row = mysqli_fetch_assoc($result);
$total_records = $row['total'];
 
// BƯỚC 3: TÌM LIMIT VÀ CURRENT_PAGE
$current_page = isset($_GET['page']) ? $_GET['page'] : 1;
$limit = 10;
 
// BƯỚC 4: TÍNH TOÁN TOTAL_PAGE VÀ START
// tổng số trang
$total_page = ceil($total_records / $limit);
 
// Hạn chế current_page trong khoảng 1 đến total_page
if ($current_page > $total_page){
    $current_page = $total_page;
}
else if ($current_page < 1){
    $current_page = 1;
}
 
// Tìm Start
$start = ($current_page - 1) * $limit;
 
// BƯỚC 5: TRUY VẤN LẤY DANH SÁCH TIN TỨC
// Có limit & start rồi thì truy vấn DataBase lấy mục lục tin tức
$result = mysqli_query($conn, "SELECT * FROM news LIMIT $start, $limit");

Phần hiển thị tin tức: Lặp mục lục tin tức & in ra, phần này chỉ lặp dữ liệu & in kết quả

// PHẦN HIỂN THỊ TIN TỨC
// BƯỚC 6: HIỂN THỊ DANH SÁCH TIN TỨC
while ($row = mysqli_fetch_assoc($result)){
    echo '<livàgt;' . $row['title'] . '</livàgt;';
}

Phần hiển thị phân trang: Hiển thị mã HTML phân trang, phần này hiển thị các nút phân trang

// PHẦN HIỂN THỊ PHÂN TRANG
// BƯỚC 7: HIỂN THỊ PHÂN TRANG
 
// nếu current_page > 1 & total_page > 1 mới hiển thị nút prev
if ($current_page > 1 && $total_page > 1) ';

 
// Lặp khoảng giữa
for ($ι = 1; $ι <= $total_page; $ι++){
    // Nếu là trang hiện thời thì hiển thị thẻ span
    // trái lại hiển thị thẻ α
    if ($ι == $current_page) ';
    
    else ';
    
}
 
// nếu current_page < $total_page & total_page > 1 mới hiển thị nút prev
if ($current_page < $total_page && $total_page > 1) ';

& đây là toàn thể file index.php

<!DOCTYPE htmlvàgt;
<htmlvàgt;
    <headvàgt;
        <titlevàgt;Chẳng hạn phân trang trong PHP & MySQLvàlt;/titlevàgt;
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </headvàgt;
    <bodyvàgt;
        <?php 
        // PHẦN XỬ LÝ PHP
        // BƯỚC 1: KẾT NỐI DataBase
        $conn = mysqli_connect('localhost', 'root', 'vertrigo', 'paging_example');
 
        // BƯỚC 2: TÌM TỔNG SỐ RECORDS
        $result = mysqli_query($conn, 'select count(id) as total from news');
        $row = mysqli_fetch_assoc($result);
        $total_records = $row['total'];
 
        // BƯỚC 3: TÌM LIMIT VÀ CURRENT_PAGE
        $current_page = isset($_GET['page']) ? $_GET['page'] : 1;
        $limit = 10;
 
        // BƯỚC 4: TÍNH TOÁN TOTAL_PAGE VÀ START
        // tổng số trang
        $total_page = ceil($total_records / $limit);
 
        // Hạn chế current_page trong khoảng 1 đến total_page
        if ($current_page > $total_page){
            $current_page = $total_page;
        }
        else if ($current_page < 1){
            $current_page = 1;
        }
 
        // Tìm Start
        $start = ($current_page - 1) * $limit;
 
        // BƯỚC 5: TRUY VẤN LẤY DANH SÁCH TIN TỨC
        // Có limit & start rồi thì truy vấn DataBase lấy mục lục tin tức
        $result = mysqli_query($conn, "SELECT * FROM news LIMIT $start, $limit");
 
        ?>
        <divvàgt;
            <?php 
            // PHẦN HIỂN THỊ TIN TỨC
            // BƯỚC 6: HIỂN THỊ DANH SÁCH TIN TỨC
            while ($row = mysqli_fetch_assoc($result)){
                echo '<livàgt;' . $row['title'] . '</livàgt;';
            }
            ?>
        </divvàgt;
        <div class="pagination">
           <?php 
            // PHẦN HIỂN THỊ PHÂN TRANG
            // BƯỚC 7: HIỂN THỊ PHÂN TRANG
 
            // nếu current_page > 1 & total_page > 1 mới hiển thị nút prev
            if ($current_page > 1 && $total_page > 1) ';
            
 
            // Lặp khoảng giữa
            for ($ι = 1; $ι <= $total_page; $ι++){
                // Nếu là trang hiện thời thì hiển thị thẻ span
                // trái lại hiển thị thẻ α
                if ($ι == $current_page) ';
                
                else ';
                
            }
 
            // nếu current_page < $total_page & total_page > 1 mới hiển thị nút prev
            if ($current_page < $total_page && $total_page > 1) ';
            
           ?>
        </divvàgt;
    </bodyvàgt;
</htmlvàgt;

Lời kết

Như thế vncoder.vn đã hướng dẫn các bạn phân trang dễ dàng bằng PHP & MySQL, bài này giành riêng cho newbie nên sẽ không bị hạn chế số trang. Chẳng hạn bạn có 1000 trang thì nó sẽ hiển thị 1000 button phân trang luôn. Nếu có gì không hiểu bạn có thể phản hồi phía dưới để được lời giải. Chúc bạn thành công!.

Xem Thêm  “Def” trong Python: Sử dụng 10 ví dụ được giải thích! - hàm def trong python

Ebook xem qua

Viết một bình luận