Thứ Bảy, 11 tháng 2, 2017

Làm thế nào để phân trang dữ liệu với PHP

Làm thế nào để phân trang dữ liệu với PHP là một câu hỏi mà nhiều bạn mới học PHP thường đặt ra. Ngày hôm nay mình sẽ hướng dẫn bạn viết code để thực hiện điều đó.



Tạo file Paginator.class.php


Đầu tiên chúng ta cần tạo 1 class Paginator như sau:

<?php
class Paginator {
     private $_conn;
        private $_limit;
        private $_page;
        private $_query;
        private $_total;
}

Sau đó bổ sung cho class thêm 1 constructor.


public function __construct( $conn, $query ) {
    $this->_conn = $conn;
    $this->_query = $query;
    $rs= $this->_conn->query( $this->_query );
    $this->_total = $rs->num_rows;
}

Khá đơn giản phải không? Constructor gán giá trị cho thuộc tính $_conn$_query bằng 2 tham số $conn$query được truyền vào và thực hiện lệnh truy vấn cần thiết, tiếp theo là gán tổng số record được lấy từ lệnh truy vấn và gán qua thuộc tính $_total. Thuộc tính $_total rất cần thiết để tạo ra các liên kết phân trang.

Lấy dữ liệu theo trang


Bây giờ chúng ta hãy tạo một phương thức để đánh số trang dữ liệu và lấy dữ liệu theo số trang. 

public function getData( $limit = 10, $page = 1 ) { 
    $this->_limit   = $limit;
    $this->_page    = $page;
    if ( $this->_limit == 'all' ) {
        $query      = $this->_query;
    } else {
        $query      = $this->_query . " LIMIT " . ( ( $this->_page - 1 )
* $this->_limit ) . ", $this->_limit";
    }
    $rs             = $this->_conn->query( $query );
    while ( $row = $rs->fetch_assoc() ) {
        $results[]  = $row;
    }
   $result         = new stdClass();
    $result->page   = $this->_page;
    $result->limit  = $this->_limit;
    $result->total  = $this->_total;
    $result->data   = $results;
    return $result;
}

Tham số $limit đại diện cho số lượng record hiển thị trên trang và tham số $page đại diện cho số trang mà bạn đang truy cập. Theo mặc định mình gán $limit = 10, bạn có thể thay đổi giá trị này tùy ý muốn. Đoạn lệnh if else để kiểm tra xem nếu người dùng muốn lấy dữ liệu theo trang thay vì xem toàn bộ. Nếu người dùng muốn xem dữ liệu theo trang thì mình tiến hành nối thêm chuỗi LIMIT ... để lấy dữ liệu theo trang đó dựa vào lệnh truy vấn SQL. Cuối cùng là thực hiện truy vấn cơ sở dữ liệu theo biến $query, gán qua đối tượng result và trả về kết quả.

Hiển thị liên kết phân trang


Việc hiển thị liên kết phân trang là rất quan trọng. Bạn phải code để các liên kết được hiển thị hợp lý khiến người dùng dễ sử dụng. Ở bài viết này thì bạn không cần lo về vấn đề này vì các liên kết được tạo ra sẽ rất hợp lý và logic.

Bây giờ chúng ta sẽ tạo phương thức để có được các liên kết.

<?php
public function createLinks( $links, $list_class ) {
    if ( $this->_limit == 'all' ) {
        return '';
    }
    $last       = ceil( $this->_total / $this->_limit );
    $start      = ( ( $this->_page - $links ) > 0 ) ? $this->_page - $links
: 1;
    $end        = ( ( $this->_page + $links ) < $last ) ?
$this->_page + $links : $last;
    $html       = '<ul class="' . $list_class . '">';
    $class      = ( $this->_page == 1 ) ? "disabled" : "";
    $html       .= '<li class="' . $class . '"><a href="?limit='
.$this->_limit . '&page=' . ( $this->_page - 1 )
. '">&laquo;</a></li>';
    if ( $start > 1 ) {
        $html   .= '<li><a href="?limit=' . $this->_limit .
'&page=1">1</a></li>';
        $html   .= '<li class="disabled"><span>...</span></li>';
    }
    for ( $i = $start ; $i <= $end; $i++ ) {
        $class  = ( $this->_page == $i ) ? "active" : "";
        $html   .= '<li class="' . $class
. '"><a href="?limit=' . $this->_limit
. '&page=' . $i . '">' . $i . '</a></li>';
    }
    if ( $end < $last ) {
        $html   .= '<li class="disabled"><span>...</span></li>';
        $html   .= '<li><a href="?limit=' . $this->_limit . '&page='
. $last . '">' . $last . '</a></li>';
    }
    $class      = ( $this->_page == $last ) ? "disabled" : "";
    $html       .= '<li class="' . $class . '"><a href="?limit='
. $this->_limit. '&page=' . ( $this->_page + 1 )
. '">&raquo;</a></li>';
    $html       .= '</ul>'; 
    return $html;
}

Index.php 


Bây giờ chúng ta sẽ tạo ra tập tin index.php để sử dụng class Paginator. Nội dung file index.php chỉ đơn giản như thế này: 

<!DOCTYPE html>
    <head>
        <title>PHP Pagination</title>
        <link rel="stylesheet" href="css/bootstrap.min.css">
    </head>
    <body>
        <div class="container">
                <div class="col-md-10 col-md-offset-1">
                <h1>PHP Pagination</h1>
                <table class="table table-striped table-condensed
table-bordered table-rounded">
                        <thead>
                                <tr>
                                <th>City</th>
                                <th width="20%">Country</th>
                                <th width="20%">Continent</th>
                                <th width="25%">Region</th>
                        </tr>
                        </thead>
                        <tbody></tbody>
                </table>
                </div>
        </div>
        </body>
</html>


Sử dụng Paginator


Sử dụng class Paginator bằng cách thêm đoạn lệnh sau vào đầu file index.php:

<?php
    require_once 'Paginator.class.php';
    $conn       = new mysqli( '127.0.0.1', 'root', 'root', 'world' );
    $limit      = ( isset( $_GET['limit'] ) ) ? $_GET['limit'] : 25;
    $page       = ( isset( $_GET['page'] ) ) ? $_GET['page'] : 1;
    $links      = ( isset( $_GET['links'] ) ) ? $_GET['links'] : 7;
    $query      = "SELECT City.Name, City.CountryCode, Country.Code,
Country.Name AS Country, Country.Continent,
Country.Region FROM City, Country
WHERE City.CountryCode = Country.Code";
    $Paginator  = new Paginator( $conn, $query );
    $results    = $Paginator->getData( $limit, $page );
?>

Hiển thị kết quả


Bây giờ để hiển thị kết quả thu được thì bạn thêm đoạn lệnh sau vào thẻ tbody:

<?php for( $i = 0; $i < count( $results->data ); $i++ ) : ?>
        <tr>
                <td><?php echo $results->data[$i]['Name']; ?></td>
                <td><?php echo $results->data[$i]['Country']; ?></td>
                <td><?php echo $results->data[$i]['Continent']; ?></td>
                <td><?php echo $results->data[$i]['Region']; ?></td>
        </tr>
<?php endfor; ?>


Liên kết phân trang


Để hiển thị các liên kết phân trang bên dưới table thì bạn thêm đoạn lệnh sau vào dưới thẻ table:

<?php echo $Paginator->createLinks( $links, 'pagination pagination-sm' ); ?>

Kết quả ta được như hình dưới.

Project demo của bài viết bạn có thể tải về tại địa chỉ goo.gl/xEOLy5content_copyCopy short URL. Hi vọng bài viết sẽ giúp bạn thật nhiều. Hẹn gặp lại ở các bài viết PHP khác. 

1 Comments so far


EmoticonEmoticon