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 2021) 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 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
Dự án mới của mình là gamehow.net, mời anh em ghé thăm và góp ý ạ.

Giới hạn số trang trong thuật toán phân trang

Như ở bài tìm hiểu thuật toán phân trang tôi đã trình bày về thuật toán phân trang đơn giản, bạn thấy rằng nếu ta tính ra có 1000 trang thì với thuật toán đó cũng sẽ show ra hết, như vậy website của bạn nhìn sẽ cùi :D. Vì thế trong bài này tôi sẽ hướng dẫn nâng cấp lại kết quả ở bài trước để hiển thị trong một giới hạn nào đó thôi.

1. Xác định khoảng hiển thị min và max khi phân trang

Rất là rõ ràng, muốn hiển thị một số trang nào đó thì trước tiên ta phải xác định được nó sẽ hiển thị trong khoảng nào. Và ở bài này tôi sẽ hiển thị phân trang ở dạng như hình dưới đây:

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.

xac dinh khoang phan trang png

Với cách hiển thị này ta sẽ truyền vào một tham số là số trang muốn hiển thị (range). Dựa vào số trang này ta sẽ đi tìm MIN và MAX (trang bắt đầu và trang kết thúc). Cách tính sẽ rơi vào các trường hợp sau đây:

  • Trường hợp số trang hiện tại bé hơn (RANGE/2). Như vậy MIN ta gán = 0 và MAX chính là RANGE
  • Trường hợp số trang hiện tại lớn hơn (TOTAL_PAGE - (RANGE/2)). Như vậy ta gán MAX chính là TOTAL_PAGE và min sẽ bằng TOTAL_PAGE - RANGE
  • Trường hợp còn lại sẽ nằm ở giưa, như vậy ta sẽ tính MIN = CURRENT_PAGE - (RANGE/2) và MAX = (CURRENT_PAGE+(RANGE/2))

Đây chỉ là cách tính trong lý thuyết, còn trong thực tế số trang bắt đầu bằng 1 nên khi tính min, max ở:

  • Trường hợp 3 ta sẽ cộng cho 1 cho min, và trừ 1 cho max.
  • Trường hợp 2 thì ta cộng 1 cho min.
  • Trường hợp 1 giữ nguyên.

2. Nội dung thuật toán phân trang có giới hạn

class Pagination
{
    protected $_config = array(
        'current_page'  => 1, // Trang hiện tại
        'total_record'  => 1, // Tổng số record
        'total_page'    => 1, // Tổng số trang
        'limit'         => 10,// limit
        'start'         => 0, // start
        'link_full'     => '',// Link full có dạng như sau: domain/com/page/{page}
        'link_first'    => '',// Link trang đầu tiên
        'range'         => 9, // Số button trang bạn muốn hiển thị 
        'min'           => 0, // Tham số min
        'max'           => 0  // tham số max, min và max là 2 tham số private
    );
    
    /*
     * Hàm khởi tạo ban đầu để sử dụng phân trang
     */
    function init($config = array())
    {
        /*
         * Lặp qua từng phần tử config truyền vào và gán vào config của đối tượng
         * trước khi gán vào thì phải kiểm tra thông số config truyền vào có nằm
         * trong hệ thống config không, nếu có thì mới gán
         */
        foreach ($config as $key => $val){
            if (isset($this->_config[$key])){
                $this->_config[$key] = $val;
            }
        }
        
        /*
         * Kiểm tra thông số limit truyền vào có nhỏ hơn 0 hay không?
         * Nếu nhỏ hơn thì gán cho limit = 0, vì trong mysql không cho limit bé hơn 0
         */
        if ($this->_config['limit'] < 0){
            $this->_config['limit'] = 0;
        }
        
        /*
         * Tính total page, công tức tính tổng số trang như sau: 
         * total_page = ciel(total_record/limit).
         * Tại sao lại như vậy? Đây là công thức tính trung bình thôi, ví
         * dụ tôi có 1000 record và tôi muốn mỗi trang là 100 record thì 
         * đương nhiên sẽ lấy 1000/100 = 10 trang đúng không nào :D
         */
        $this->_config['total_page'] = ceil($this->_config['total_record'] / $this->_config['limit']);
        
        /*
         * Sau khi có tổng số trang ta kiểm tra xem nó có nhỏ hơn 0 hay không
         * nếu nhỏ hơn 0 thì gán nó băng 1 ngay. Vì mặc định tổng số trang luôn bằng 1
         */
        if (!$this->_config['total_page']){
            $this->_config['total_page'] = 1;
        }
        
        /*
         * Trang hiện tại sẽ rơi vào một trong các trường hợp sau:
         *  - Nếu người dùng truyền vào số trang nhỏ hơn 1 thì ta sẽ gán nó = 1 
         *  - Nếu trang hiện tại người dùng truyền vào lớn hơn tổng số trang
         *    thì ta gán nó bằng tổng số trang
         * Đây là vấn đề giúp web chạy trơn tru hơn, vì đôi khi người dùng cố ý
         * thay đổi tham số trên url nhằm kiểm tra lỗi web của chúng ta
         */
        if ($this->_config['current_page'] < 1){
            $this->_config['current_page'] = 1;
        }
        
        if ($this->_config['current_page'] > $this->_config['total_page']){
            $this->_config['current_page'] = $this->_config['total_page'];
        }
        
        /* 
         * Tính start, Như bạn biết trong mysql truy vấn sẽ có limit và start
         * Muốn tính start ta phải dựa vào số trang hiện tại và số limit trên mỗi trang
         * và áp dụng công tức start = (current_page - 1)*limit
        */
        $this->_config['start'] = ($this->_config['current_page'] - 1) * $this->_config['limit'];
        
        /* 
         * Bây giờ ta tính số trang ta show ra trang web
         * Như bạn biết với những website có data lớn thì số trang có thể
         * lên tới hàng trăm trang, chẵng nhẽ ta show hết cả 100 trang?
         * Nên trong bài này tôi hướng dẫn bạn show trong một khoảng nào đó (range)
         * giống website freetuts.net vậy
        */
        
        // Trước tiên tính middle, đây chính là số nằm giữa trong khoảng tổng số trang
        // mà bạn muốn hiển thị ra màn hình
        $middle = ceil($this->_config['range'] / 2);

        // Ta sẽ lâm vào các trường hợp như bên dưới
        // Trong trường hợp này thì nếu tổng số trang mà bé hơn range
        // thì ta show hết luôn, không cần tính toán làm gì
        // tức là gán min = 1 và max = tổng số trang luôn
        if ($this->_config['total_page'] < $this->_config['range']){
            $this->_config['min'] = 1;
            $this->_config['max'] = $this->_config['total_page'];
        }
        // Trường hợp tổng số trang mà lớn hơn range
        else
        {
            // Ta sẽ gán min = current_page - (middle + 1)
            $this->_config['min'] = $this->_config['current_page'] - $middle + 1;
            
            // Ta sẽ gán max = current_page + (middle - 1)
            $this->_config['max'] = $this->_config['current_page'] + $middle - 1;
            
            // Sau khi tính min và max ta sẽ kiểm tra
            // nếu min < 1 thì ta sẽ gán min = 1  và max bằng luôn range
            if ($this->_config['min'] < 1){
                $this->_config['min'] = 1;
                $this->_config['max'] = $this->_config['range'];
            }
            
            // Ngược lại nếu min > tổng số trang
            // ta gán max = tổng số trang và min = (tổng số trang - range) + 1 
            else if ($this->_config['max'] > $this->_config['total_page']) 
            {
                $this->_config['max'] = $this->_config['total_page'];
                $this->_config['min'] = $this->_config['total_page'] - $this->_config['range'] + 1;
            }
        }
    }
    
    /*
     * Hàm lấy link theo trang
     */
    private function __link($page)
    {
        // Nếu trang < 1 thì ta sẽ lấy link first
        if ($page <= 1 && $this->_config['link_first']){
            return $this->_config['link_first'];
        }
        // Ngược lại ta lấy link_full
        // Như tôi comment ở trên, link full có dạng domain.com/page/{page}.
        // Trong đó {page} là nơi bạn muốn số trang sẽ thay thế vào
        return str_replace('{page}', $page, $this->_config['link_full']);
    }
    
    /*
     * Hàm lấy mã html
     * Hàm này ban tạo giống theo giao diện của bạn
     * tôi không có config nhiều vì rất rối
     * Bạn thay đổi theo giao diện của bạn nhé
     */
    function html()
    {   
        $p = '';
        if ($this->_config['total_record'] > $this->_config['limit'])
        {
            $p = '<ul>';
            
            // Nút prev và first
            if ($this->_config['current_page'] > 1)
            {
                $p .= '<li><a href="'.$this->__link('1').'">First</a></li>';
                $p .= '<li><a href="'.$this->__link($this->_config['current_page']-1).'">Prev</a></li>';
            }
            
            // lặp trong khoảng cách giữa min và max để hiển thị các nút
            for ($i = $this->_config['min']; $i <= $this->_config['max']; $i++)
            {
                // Trang hiện tại
                if ($this->_config['current_page'] == $i){
                    $p .= '<li><span>'.$i.'</span></li>';
                }
                else{
                    $p .= '<li><a href="'.$this->__link($i).'">'.$i.'</a></li>';
                }
            }

            // Nút last và next
            if ($this->_config['current_page'] < $this->_config['total_page'])
            {
                $p .= '<li><a href="'.$this->__link($this->_config['current_page'] + 1).'">Next</a></li>';
                $p .= '<li><a href="'.$this->__link($this->_config['total_page']).'">Last</a></li>';
            }
            
            $p .= '</ul>';
        }
        return $p;
    }
}


$config = array(
    'current_page'  => isset($_GET['page']) ? $_GET['page'] : 1, // Trang hiện tại
    'total_record'  => 1900, // Tổng số record
    'limit'         => 10,// limit
    'link_full'     => 'index.php?page={page}',// Link full có dạng như sau: domain/com/page/{page}
    'link_first'    => 'index.php',// Link trang đầu tiên
    'range'         => 9 // Số button trang bạn muốn hiển thị 
);

$paging = new Pagination();

$paging->init($config);

echo $paging->html();

?>

<style>
    li{float:left; margin: 3px; border: solid 1px gray;}
    a{padding: 5px;}
    span{display:inline-block; padding: 0px 3px; background: blue; color:white }
</style>
Trong phần comment tôi đã giải thích rõ rồi nên tôi không giải thích gì thêm. 

3. Lời kết

Bài này thật sự hơi khó cho những bạn chưa rành về OOP. Nhưng tôi hy vọng bạn sẽ nắm được bản chất của bài toán và từ đó sẽ tự lĩnh ngộ ra.

 

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