[Nâng cao] Phân trang trong PHP và MySQL

PHP nâng cao 12/03/2017 07:00 3387
Trong bài trước mình đã trình bày về thuật toán phân trang trong PHP và MySQL. Trong bài viết này mình sẽ hướng dẫn các bạn giới hạn số trang mà bạn muốn hiển thị trong một webpage.

Ở bài trước mình đã hướng dẫn các bạn phân trang ở mức cơ bản. Nếu các bạn chưa xem bài viết trước của mình thì mình nghĩ bạn cần xem lại một chút. Thuật toán phân trang với PHP và MySQL

Điểm yếu trong bài viết phân trang cơ bản là chúng ta sẽ hiển thị hết tất cả danh sách các trang. Nếu bạn có khoảng 100 trang mà hiển thị hết ra thì nhìn nó không đẹp mắt chút nào. Trong bài viết này mình sẽ hướng dẫn các bạn nâng cao một chút là làm thế nào để có thề giới hạn số lượng trang cần hiển thị.

Xem demo

 

Thì để làm được điều này bạn cần cung cấp thêm một số đối số đầu vào nữa.

  • $pageNum: Số trang sẽ hiển thị trên một webpage.
  • $pageStart: Số trang bắt đầu
  •  $pageEnd: Số trang kết thúc
  • $numLink: Khoảng lùi trang và khoảng tiến trang so với trang hiện tại.

Các bạn follow theo hình vẽ.

 Tôi muốn hiển thị 5 trang/webpage $pageNum = 5

Ở đây thì mình đang ở trang số 5. Thì mình muốn nó sẽ hiển thị 2 trang trước và sau so với trang hiện tại.

$numLink = 2;

Nhưng đây là cách tính tĩnh. Nếu bây giờ mình đặt

  • $pageNum = 6 Thì mình sẽ hiển thị 3 trang trước và 2 trang sau.
  • $pageNum = 7 Thì mình sẽ hiển thị 3 trang trước và trang sau.
  • $pageNum = 8 Thì mình sẽ hiển thị 4 trang trước và 3 trang sau.

Từ đó mình suy ra:

$numLink = floor($pageNum/2);

Đểm mấu chốt trong cách tính này là phải tính toán được hai tham số là $pageStart$pageEnd. Thì dưới đây là cách tính của mình.

Vì số lượng records trong CSDL mẫy có hạn nên mình sẽ giảm có $recordPerPage = 3. Nghĩa là cứ ba records sẽ nằm trong một trang.

Mình sẽ sét hai trường hợp.

Trường hợp 1: $currentPage >= $pageNum

$pageStart = $currentPage - $numLink;
if($totalPage > $currentPage+$numLink)
{
    $pageEnd = $currentPage+$numLink;
}
else if($currentPage <=$totalPage && $currentPage > $totalPage-($pageNum-1))
{
    $pageStart = $totalPage-($pageNum-1);
    $pageEnd = $totalPage;
}
else
{
    $pageEnd = $totalPage;
}

Trường hợp 2: $currentPage < $pageNum

Bạn đang ở trang Trang hiện tại nhỏ hơn trang s

// Mặc định $pageStart = 1
$pageStart = 1; 
if ($totalPage > $pageNum)
    $pageEnd = $pageNum;
else
    $pageEnd = $totalPage;

Ghép hai trường hợp trên:

if($currentPage >= $pageNum)
{
    $pageStart = $currentPage - $numLink;
    if($totalPage > $currentPage+$numLink)
    {
        $pageEnd = $currentPage+$numLink;
    }
    else if($currentPage <=$totalPage && $currentPage > $totalPage-($pageNum-1))
    {
        $pageStart = $totalPage-($pageNum-1);
        $pageEnd = $totalPage;
    }
    else
    {
        $pageEnd = $totalPage;
    }
}
else
{
    $pageStart = 1;
    if ($totalPage > $pageNum)
        $pageEnd = $pageNum;
    else
        $pageEnd = $totalPage;
}

Code hoàn chỉnh:

<?php
    define("DB_HOST", "localhost");
    /** The name of the database for demo */
    define("DB_NAME", "demo_db");
    /** MySQL database username */
    define("DB_USER", "demo_db");
    /** MySQL database password */
    define("DB_PASS", "Gu5ZwYzL");
    
    // Bước 1: Kết nối tới CSDL
    $dbconn = mysql_connect(DB_HOST,DB_USER,DB_PASS) or die('Không thể kết nối tới CSDL');
    mysql_select_db(DB_NAME, $dbconn) or die('Không thể kết nối tới CSDL!');
    
    // Bước 2: Tính tổng $totalRecords
    $query = "SELECT count(*) AS totalRecords FROM employees";
    $result = mysql_query($query, $dbconn);
    $row = mysql_fetch_assoc($result);
    $totalRecords = !empty($row) ? $row['totalRecords'] : 0;
    
    // Bước 3: Lấy $currentPage và thiết lập $recordPerPage
    $currentPage = isset($_GET['page']) && (int) $_GET['page'] > 0 ? (int) $_GET['page'] : 1;
    // Thiết lập số records/1 trang
    $recordPerPage = 3;
    // Thiết lập số trang
    $pageNum = 5;
    // Khoảng lùi và tiến danh sách trang
    $numLink = floor($pageNum/2);
    
    // Bước 4: Tính tổng số trang($totalPage) và tính $offset
    $totalPage = ceil($totalRecords/$recordPerPage);
    // Tính $offset
    $offset = ($currentPage-1)*$recordPerPage;
    $limit = "LIMIT $offset,$recordPerPage";
    
    $query = "SELECT * FROM employees ".$limit; 
    $result = mysql_query($query, $dbconn);
    
    // PHẦN HIỂN THỊ DANH SÁCH
?>
<div class="container">
    <?php if(mysql_num_rows($result) > 0){ ?>
        <table class="tbl-grid" cellpadding="0" cellspacing="0" width="100%">
            <thead><tr>
                <td class="gridheader">employeeNumber</td>
                <td class="gridheader">lastName</td>
                <td class="gridheader">firstName</td>
                <td class="gridheader">extension</td>
                <td class="gridheader">email</td>
                <td class="gridheader">officeCode</td>
                <td class="gridheader">reportsTo</td>
                <td class="gridheader">jobTitle</td>
            </tr></thead>
        <?php while ($row = mysql_fetch_assoc($result)){?>
            <tr>
                <td><?php echo $row['employeeNumber'] ?></td>
                <td><?php echo $row['lastName'] ?></td>
                <td><?php echo $row['firstName'] ?></td>
                <td><?php echo $row['extension'] ?></td>
                <td><?php echo $row['email'] ?></td>
                <td><?php echo $row['officeCode'] ?></td>
                <td><?php echo $row['reportsTo'] ?></td>
                <td><?php echo $row['jobTitle'] ?></td>
            </tr>
        <?php } ?>
        </table>
    <?php } ?>
    
    <br />
    <div class="pagination">
        <?php
        // Button trang trước
        if($currentPage > 1 && $totalPage > 0){
            echo '<a href="index[nc].php?page='.($currentPage-1).'&t='.time().'">&larr;</a>';
        }
        // Danh sách trang
        if($currentPage >= $pageNum){
            $pageStart = $currentPage - $numLink;
            if($totalPage > $currentPage+$numLink){
                $pageEnd = $currentPage+$numLink;
            }
            else if($currentPage <=$totalPage && $currentPage > $totalPage-($pageNum-1)){
                $pageStart = $totalPage-($pageNum-1);
                $pageEnd = $totalPage;
            }
            else{
                $pageEnd = $totalPage;
            }
        }else{
            $pageStart = 1;
             if ($totalPage > $pageNum)
                $pageEnd = $pageNum;
            else
                $pageEnd = $totalPage;
        }
        // Lặp và in danh sách trang
        for($i=$pageStart; $i<=$pageEnd; $i++){
            echo '<a'.($currentPage==$i?' class="current"':'').' href="index[nc].php?page='.$i.'&t='.time().'">'.$i.'</a>';
        }
        
        // Button trang kế tiếp
        if($currentPage < $totalPage && $totalPage > 1){
            echo '<a href="index[nc].php?page='.($currentPage+1).'&t='.time().'">&rarr;</a>';
        }
        ?>
    </div>
</div>

Tổng kết:

OK ! Như vậy là mình đã hướng dẫn các bạn hoàn thành phần phân trang trong PHP kết hợp với MySQL. Nếu có thể mình sẽ hướng dẫn các bạn tạo một class phân trang hoàn chỉnh.

Xem Thêm

Profile photo of adminTheHalfHeart

B.V.T

Sinh ra và lớn nên ở Bắc Giang. Hiện tại thì tôi đang là một lập trình viên tại VietISO. Tôi lập website này với mục đích là bookmark những gì tôi đã đọc qua và mong muốn chia sẻ những gì tôi biết.