PHP TUTORIALS
Hướng dẫn tạo domain ảo tại localhost với XAMPP trên Window Có gì mới trong PHP 8 (Tính năng, Cải tiến và Trình biên dịch JIT) Hướng dẫn viết ứng dụng kiểm tra năm sinh theo âm lịch bằng PHP Xử lý realtime trong PHP sử dụng pusher Hướng dẫn gửi mail trong PHP với PHPMailer Bóc tách dữ liệu từ trang khác bằng PHP Simple HTML DOM Parser Cách sửa lỗi hình ảnh khi đăng bài viết lên Facebook Hướng dẫn tạo thông báo realtime với pushcrew Kích thước chuẩn và cách làm FavIcon icon Tìm hiểu bản chất vòng lặp foreach trong php Những vấn đề nâng cao kỹ năng lập trình trong php Sử Dụng Vòng Lặp Xuất Dữ Liệu Bảng Tính Lương Tìm hiểu thuật toán phân trang trong php Giới hạn số trang trong thuật toán phân trang Bài 01: Đệ quy menu đa cấp với php và mysql - phần 1 Bài 02: Đệ quy menu đa cấp với php và mysql - phần 2 Tích hợp bộ search google vào website Nên dùng count() hay sizeof() để đếm số phần tử của mảng Bài 01: Lấy dữ liệu từ mysql lưu vào file excel với PHPExcel Tạo slug tự động bằng JavaScript và PHP RSS là gì? Cách Tạo RSS cho Website PHP CMS là gì? Các CMS phổ biến hiện nay (update 2024) Web động là gì? Web tĩnh là gì? Chặn referrer từ website simple-share-buttons.com Bảng mã ASCII chuẩn các hệ nhị phân - thập phân - thập lục phân Hướng dẫn tạo Facebook App để lấy App ID và Secret Key Download Facebook SDK cho PHP Mối liên hệ giữa HTML - PHP - MYSQL Tự động post bài viết lên tường với hootsuite.com Kiểm tra người dùng đã đăng nhập hay chưa bằng PHP Lấy video kênh Youtube mới nhất bằng jQuery và Youtube API V3 Đệ quy chuyên mục đa cấp trong PHP toàn tập Font Awesome là gì? Cách sử dụng Font Awesome Tích hợp đăng nhập Google vào Website Thuật toán phân trang với PHP và MySQL Cài đặt LAMP trên Fedora
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Thuật toán phân trang với PHP và MySQL

Trên freetuts.net đã có hai bài viết về thuật toán phân trang rồi nhưng những bài đó sử dụng kiến thức của lập trình hướng đối tượng nên rất khó tiếp cận với những bạn mới học PHP, vì vậy trong bài này mình sẽ hướng dẫn các bạn phân trang sử dụng PHP căn bản kết hợp với MySQL. Lưu ý là trong thuật toán này sẽ không có giới hạn số trang.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

1. Ý tưởng thuật toán phân trang

Trường hợp 1Phân trang cho bảng tin tức và 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? Để giải quyết vấn đề này thì ta sử dụng LIMIT trong MySQL. Như vậy 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ẻ và 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.

Bài viết này được đăng tại [free tuts .net]

Ví dụ: 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.

Bây giờ là làm thế nào để xác định 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.

Định nghĩa:

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

Và đây là công thức tính start:

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

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

2. 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 tại: Dựa vào 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 ví dụ sử dụng MySQL và PHP để phân trang luôn. 

Tạo database:

Bạn tạo một database tên là paging_example và 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. Tiếp theo ta insert vào một số dữ liệu để chạy demo.

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 và sau đó copy đoạn mã HTML dưới đây:

<!DOCTYPE html>
<html>
    <head>
        <title>Ví dụ phân trang trong PHP và MySQL</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <?php 
        // PHẦN XỬ LÝ PHP
        ?>
        <div>
            <?php 
            // PHẦN HIỂN THỊ TIN TỨC
            ?>
        </div>
        <div class="pagination">
           <?php 
            // PHẦN HIỂN THỊ PHÂN TRANG
           ?>
        </div>
    </body>
</html>

Trong layout mình có 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

Bây giờ ta code cho từng phần nhé.

Phần xử lý PHP: Phần này xử lý truy vấn CSDL và thuật toán phân trang, phần này khá quan trọng bởi nó tính toán các thông số phân trang và khởi tạo các biến sử dụng cho các phần còn lại.

// PHẦN XỬ LÝ PHP
// BƯỚC 1: KẾT NỐI CSDL
$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);

// Giới hạn 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 và start rồi thì truy vấn CSDL lấy danh sách tin tức
$result = mysqli_query($conn, "SELECT * FROM news LIMIT $start, $limit");

Phần hiển thị tin tức: Lặp danh sách tin tức và in ra, phần này chỉ lặp dữ liệu và 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 '<li>' . $row['title'] . '</li>';
}

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 và total_page > 1 mới hiển thị nút prev
if ($current_page > 1 && $total_page > 1){
    echo '<a href="index.php?page='.($current_page-1).'">Prev</a> | ';
}

// Lặp khoảng giữa
for ($i = 1; $i <= $total_page; $i++){
    // Nếu là trang hiện tại thì hiển thị thẻ span
    // ngược lại hiển thị thẻ a
    if ($i == $current_page){
        echo '<span>'.$i.'</span> | ';
    }
    else{
        echo '<a href="index.php?page='.$i.'">'.$i.'</a> | ';
    }
}

// nếu current_page < $total_page và total_page > 1 mới hiển thị nút prev
if ($current_page < $total_page && $total_page > 1){
    echo '<a href="index.php?page='.($current_page+1).'">Next</a> | ';
}

Và đây là toàn bộ file index.php.

<!DOCTYPE html>
<html>
    <head>
        <title>Ví dụ phân trang trong PHP và MySQL</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <?php 
        // PHẦN XỬ LÝ PHP
        // BƯỚC 1: KẾT NỐI CSDL
        $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);

        // Giới hạn 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 và start rồi thì truy vấn CSDL lấy danh sách tin tức
        $result = mysqli_query($conn, "SELECT * FROM news LIMIT $start, $limit");

        ?>
        <div>
            <?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 '<li>' . $row['title'] . '</li>';
            }
            ?>
        </div>
        <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 và total_page > 1 mới hiển thị nút prev
            if ($current_page > 1 && $total_page > 1){
                echo '<a href="index.php?page='.($current_page-1).'">Prev</a> | ';
            }

            // Lặp khoảng giữa
            for ($i = 1; $i <= $total_page; $i++){
                // Nếu là trang hiện tại thì hiển thị thẻ span
                // ngược lại hiển thị thẻ a
                if ($i == $current_page){
                    echo '<span>'.$i.'</span> | ';
                }
                else{
                    echo '<a href="index.php?page='.$i.'">'.$i.'</a> | ';
                }
            }

            // nếu current_page < $total_page và total_page > 1 mới hiển thị nút prev
            if ($current_page < $total_page && $total_page > 1){
                echo '<a href="index.php?page='.($current_page+1).'">Next</a> | ';
            }
           ?>
        </div>
    </body>
</html>

3. Lời kết

Như vậy mình đã hướng dẫn các bạn phân trang đơn giản bằng PHP và MySQL, bài này dành cho newbie nên sẽ không bị giới hạn số trang. Ví dụ bạn có 1000 trang thì nó sẽ hiển thị 1000 button phân trang luôn. Như ở freetuts bạn thấy nếu mình ở trang 10 thì nó sẽ xuất hiện khoảng từ trang số 6 đến trang số 14. 

Cùng chuyên mục:

Hàm key_exists() trong PHP

Hàm key_exists() trong PHP

Cách sử dụng key_exists() trong PHP

Hàm mysqli_fetch_row() trong PHP

Hàm mysqli_fetch_row() trong PHP

Cách sử dụng mysqli_fetch_row() trong PHP

Hàm end() trong PHP

Hàm end() trong PHP

Cách sử dụng end() trong PHP

Hàm mysqli_field_count() trong PHP

Hàm mysqli_field_count() trong PHP

Cách sử dụng mysqli_field_count() trong PHP

Hàm count() trong PHP

Hàm count() trong PHP

Cách sử dụng count() trong PHP

Hàm mysqli_field_seek() trong PHP

Hàm mysqli_field_seek() trong PHP

Cách sử dụng mysqli_field_seek() trong PHP

Hàm compact() trong PHP

Hàm compact() trong PHP

Cách sử dụng compact() trong PHP

Hàm mysqli_field_tell() trong PHP

Hàm mysqli_field_tell() trong PHP

Cách sử dụng mysqli_field_tell() trong PHP

Hàm array_values() trong PHP

Hàm array_values() trong PHP

Cách sử dụng array_values() trong PHP

Hàm mysqli_free_result() trong PHP

Hàm mysqli_free_result() trong PHP

Cách sử dụng mysqli_free_result() trong PHP

Hàm array_unshift() trong PHP

Hàm array_unshift() trong PHP

Cách sử dụng array_unshift() trong PHP

Hàm mysqli_get_charset() trong PHP

Hàm mysqli_get_charset() trong PHP

Cách sử dụng mysqli_get_charset() trong PHP

Hàm array_shift() trong PHP

Hàm array_shift() trong PHP

Cách sử dụng array_shift() trong PHP

Hàm mysqli_get_client_stats() trong PHP

Hàm mysqli_get_client_stats() trong PHP

Cách sử dụng mysqli_get_client_stats() trong PHP

Hàm array_unique() trong PHP

Hàm array_unique() trong PHP

Cách sử dụng array_unique() trong PHP

Hàm mysqli_get_client_version() trong PHP

Hàm mysqli_get_client_version() trong PHP

Cách sử dụng mysqli_get_client_version() trong PHP

Hàm array_uintesect() trong PHP

Hàm array_uintesect() trong PHP

Cách sử dụng array_uintesect() trong PHP

Hàm mysqli_get_connection_stats() trong PHP

Hàm mysqli_get_connection_stats() trong PHP

Cách sử dụng mysqli_get_connection_stats() trong PHP

Hàm array_sum() trong PHP

Hàm array_sum() trong PHP

Cách sử dụng array_sum() trong PHP

Hàm mysqli_get_host_info() trong PHP

Hàm mysqli_get_host_info() trong PHP

Cách sử dụng mysqli_get_host_info() trong PHP

Top