Thứ Năm, 29 tháng 9, 2016

PHP nâng cao - Class phân trang trong PHP

Tại sao phải phân trang? khi trang web của chúng ta có quá nhiều nội dung dẫn đến việc dữ liệu bị đổ ra một cách tràn lan bừa bãi không theo thứ tự nào cả. Dẫn đến hiển thị dữ liệu bị dối gây khó khăn cho người dùng khi vào đọc nội dung. Việc phân trang giúp ta trình bày trang web gọn gàng trong sáng hơn
Về thuật toán phân trang ở đây chúng ta sẽ không nói lại ví dụ như là tại sao thuật toán tìm trang hiện tại lại là (Start/limit + 1),  tìm số trang lại là ceil(total/limt)..., Chúng ta sẽ tập trung lại các chức năng chính trong một class, khi chúng ta cần phân trang cho một module nào đó chỉ việc gọi class phân trang vào là xong

- Demo phân trang

Class phân trang đơn giản

Ở đây tôi đã có một bảng tbl_user. Ta sẽ tiến hành phân trang cho danh sách User.

Class Pagination có các thuộc tính và phương thức sau

1
2
3
4
5
6
7
8
9
10
11
12
13
class Pagination{
  
 public $limit;
 protected $_baseUrl;
  
 public function __construct(){}
         
        public function start(){} // Tìm start
 
        public function totalPages(){} // Tìm tổng số trang
 
        public function listPages(){} // Lấy ra list trang
}

Trong đó :

public : $limit là số record hiển thị trên một trang
protected : $_baseUrl lấy ra Url trang web

- Hàm Start() tìm vị trí start từ Url
- Hàm totalPages() tìm xem danh sách User có tất cả bao nhiêu trang
- Hàm listPages() trả về danh sách trang tìm được

Đây là toàn bộ code của class Phân trang

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?php
/**
- Pagination
- Author : Localhost
- Phpandmysql.net
*/
class Pagination{
  
 public $limit = 3; // số record hiển thị trên một trang
 protected $_baseUrl;
  
 public function __construct(){
  $this->_baseUrl = $_SERVER['PHP_SELF'];
 }
 /**
   - Tìm ra vị trí start
 */
 public function start(){
  if(isset($_GET['start'])){
   $start = $_GET['start'];
  }else{
   $start = 0;
  }
  return $start;
 }
  
 /**
   - Tìm ra tổng số trang
 */
 public function totalPages($totalRecord){
  if(isset($_GET['pages'])){
   $totalPages = $_GET['pages'];
  }else{
   $totalPages = ceil($totalRecord/$this->limit);
  }
  return $totalPages;
 }
  
 /**
   - Gọi ra list phân trang
 */
 public function listPages($totalPages){
  $start = $this->start();
  $limit = $this->limit;
  $listPage = '';
   
  if($totalPages > 1){ // số trang phải từ 2 trang trở lên
   $current = ($start/$limit) + 1; // trang hiện tại
   if($current != 1){ // Nút prev
    $newstart = $start - $limit;
    $listPage .= "<a href='".$this->_baseUrl."?pages=$totalPages&start=$newstart'>Prev</a>";
   }
    
   for($i=1;$i<=$totalPages;$i++){  // Tất cả các trang tìm được
    $newstart = ($i - 1)*$limit;
    if($i == $current){
     $listPage .= "<span class='current'>".$i."</span>";
    }else{
     $listPage .= "<a href='".$this->_baseUrl."?pages=$totalPages&start=$newstart'>".$i."</a>";
    }
   }
    
   if($current != $totalPages){ // Nút next
    $newstart = $start + $limit;
    $listPage .= "<a href='".$this->_baseUrl."?pages=$totalPages&start=$newstart'>Next</a>";
   }
  }
   
  return $listPage;
 }
}

Sử dụng như thế nào? Như đã nói ở các bài trước thì cái hay của lập trình hướng đối tượng là chúng ta làm một lần để sử dụng nhiều lần. Chúng ta đã có class Pagination rùi thì việc các bạn muốn phân trang cho bất cứ đối tượng nào bạn muốn như mà News, Products... mà ta chỉ sử dụng duy nhất một class mà thôi.

Để sử dụng ta chỉ cẩn gọi class vào và khởi tạo đối tượng truyền các tham số cần thiết

Tại file index.php - module cần phân trang

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php require("libraries/config.php"); // gọi file config.php ?>
<?php require("libraries/database.php"); // gọi file database.php ?>
<?php require("libraries/user.php"); // gọi class User ?>
<?php require("libraries/pagination.php"); // gọi file pagination.php ?>
<h3>CLASS PAGINATION BASIC</h3>
<p>Học php tại phpandmysql.net</p>
<hr />
<?php
$Pagination = new Pagination();
$User = new User(); // Khởi tạo class User
 
$limit = $Pagination->limit; // Số record hiển thị trên một trang
$stat = $Pagination->start(); // Vị trí của record
$totalRecord = $User->totalRecord(); // Tổng số user có trong database
$totalPages = $Pagination->totalPages($totalRecord); // Tổng số trang tìm được
 
$listUsers = $User->listUsers($stat, $limit); // List user

Sử dụng :

- $Pagination->limit ; lấy ra limit từ class Pagination
- $Pagination->start(); lấy ra start
- $User->totalRecord(); lấy ra tổng số User từ database
- $Pagination->totalPages($totalRecord); Tổng số page tìm được
- $User->listUssers($start, $limit); List users

Sau khi đã truyền đủ các thông số thì ta sẽ lấy được danh sách phân trang qua hàm listPages()

1
$Pagination->listPages($totalPages);
Cuối cùng là đổ danh sách phân trang ra chỗ nào mà bạn muốn, Ở đây tôi đang đổ ra thẻ <div id='pagination'></div>

1
2
3
4
<!-- List phân trang -->
<div id="pagination">
<?php echo $Pagination->listPages($totalPages); ?>
</div>

Note : Ở bài này tôi không hướng dẫn các bạn thuật toán phân trang nữa vì nó quá dài mà mục đích tôi muốn hướng dẫn các bạn cách chuyển từ cách code thủ tục sang hướng đối tượng. Đây là class phân trang đơn giản nhất mà tôi viết ra, nó còn thiếu rất nhiều thứ. Tuy nhiên các bạn mới học có thể dựa vào để base cho mình khi hiểu được nó các bạn có thể xây dựng riêng theo phong cách của mình.

Nếu các bạn chưa hiểu có thể download ví dụ ở đây để xem nhé.
nguồn http://phpandmysql.net/


EmoticonEmoticon